Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ | 5 #ifndef BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ |
| 6 #define BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ | 6 #define BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ |
| 7 | 7 |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/base_export.h" | 13 #include "base/base_export.h" |
| 14 #include "base/callback.h" | 14 #include "base/callback.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
| 17 | 17 |
| 18 namespace base { | 18 namespace base { |
| 19 | 19 |
| 20 class SequencedTaskRunner; | 20 class SequencedTaskRunner; |
| 21 | 21 |
| 22 namespace trace_event { | 22 namespace trace_event { |
| 23 | 23 |
| 24 struct MemoryDumpProviderInfo; | 24 struct MemoryDumpProviderInfo; |
| 25 | 25 |
| 26 // Detects temporally local memory peaks. Peak detection is based on | |
| 27 // continuously querying memory usage using MemoryDumpprovider(s) that support | |
| 28 // fast polling (e.g., ProcessMetricsDumpProvider which under the hoods reads | |
| 29 // /proc/PID/statm on Linux) and using a cobination of: | |
| 30 // - An static threshold (currently 1% of total system memory). | |
| 31 // - Sliding window stddev analysis. | |
| 32 // Design doc: https://goo.gl/0kOU4A . | |
| 26 // This class is NOT thread-safe, the caller has to ensure linearization of | 33 // This class is NOT thread-safe, the caller has to ensure linearization of |
| 27 // the calls to the public methods. In any case, the public methods do NOT have | 34 // the calls to the public methods. In any case, the public methods do NOT have |
| 28 // to be called from the |task_runner| on which the polling tasks run. | 35 // to be called from the |task_runner| on which the polling tasks run. |
| 29 class BASE_EXPORT MemoryPeakDetector { | 36 class BASE_EXPORT MemoryPeakDetector { |
| 30 public: | 37 public: |
| 31 using OnPeakDetectedCallback = RepeatingClosure; | 38 using OnPeakDetectedCallback = RepeatingClosure; |
| 32 using DumpProvidersList = std::vector<scoped_refptr<MemoryDumpProviderInfo>>; | 39 using DumpProvidersList = std::vector<scoped_refptr<MemoryDumpProviderInfo>>; |
| 33 using GetDumpProvidersFunction = RepeatingCallback<void(DumpProvidersList*)>; | 40 using GetDumpProvidersFunction = RepeatingCallback<void(DumpProvidersList*)>; |
| 34 | 41 |
| 35 enum State { | 42 enum State { |
| 36 NOT_INITIALIZED = 0, // Before Setup() | 43 NOT_INITIALIZED = 0, // Before Setup() |
| 37 DISABLED, // Before Start() or after Stop(). | 44 DISABLED, // Before Start() or after Stop(). |
| 38 ENABLED, // After Start() but no dump_providers_ are available. | 45 ENABLED, // After Start() but no dump_providers_ are available. |
| 39 RUNNING // After Start(). The PollMemoryAndDetectPeak() task is scheduled. | 46 RUNNING // After Start(). The PollMemoryAndDetectPeak() task is scheduled. |
| 40 }; | 47 }; |
| 41 | 48 |
| 49 // Peak detector configuration, passed to Start(). | |
| 50 struct Config { | |
| 51 // The rate at which memory will be polled. Polls will happen on the task | |
| 52 // runner passed to Setup(). | |
| 53 uint32_t polling_interval_ms; | |
| 54 | |
| 55 // Guarantees that a peak detection callback will never before than the | |
|
ssid
2017/04/10 20:55:06
"will never before than"?
Primiano Tucci (use gerrit)
2017/04/11 11:12:09
reworded
| |
| 56 // specified amount of time from the last one. | |
| 57 uint32_t min_time_between_peaks_ms; | |
| 58 | |
| 59 // When enabled causes a TRACE_COUNTER event to be injected in the trace | |
| 60 // for each poll (if tracing is enabled). | |
| 61 bool enable_verbose_poll_tracing; | |
| 62 }; | |
| 63 | |
| 42 static MemoryPeakDetector* GetInstance(); | 64 static MemoryPeakDetector* GetInstance(); |
| 43 | 65 |
| 44 // Configures the peak detector, binding the polling tasks on the given | 66 // Configures the peak detector, binding the polling tasks on the given |
| 45 // thread. Setup() can be called several times, provided that: (1) Stop() | 67 // thread. Setup() can be called several times, provided that: (1) Stop() |
| 46 // is called; (2a) the previous task_runner is flushed or (2b) the task_runner | 68 // is called; (2a) the previous task_runner is flushed or (2b) the task_runner |
| 47 // remains the same. | 69 // remains the same. |
| 48 // GetDumpProvidersFunction: is the function that will be invoked to get | 70 // GetDumpProvidersFunction: is the function that will be invoked to get |
| 49 // an updated list of polling-capable dump providers. This is really just | 71 // an updated list of polling-capable dump providers. This is really just |
| 50 // MemoryDumpManager::GetDumpProvidersForPolling, but this extra level of | 72 // MemoryDumpManager::GetDumpProvidersForPolling, but this extra level of |
| 51 // indirection allows easier testing. | 73 // indirection allows easier testing. |
| 52 // SequencedTaskRunner: the task runner where PollMemoryAndDetectPeak() will | 74 // SequencedTaskRunner: the task runner where PollMemoryAndDetectPeak() will |
| 53 // be periodically called. | 75 // be periodically called. |
| 54 // OnPeakDetectedCallback: a callback that will be invoked on the | 76 // OnPeakDetectedCallback: a callback that will be invoked on the |
| 55 // given task runner when a memory peak is detected. | 77 // given task runner when a memory peak is detected. |
| 56 void Setup(const GetDumpProvidersFunction&, | 78 void Setup(const GetDumpProvidersFunction&, |
| 57 const scoped_refptr<SequencedTaskRunner>&, | 79 const scoped_refptr<SequencedTaskRunner>&, |
| 58 const OnPeakDetectedCallback&); | 80 const OnPeakDetectedCallback&); |
| 59 | 81 |
| 60 // Releases the |task_runner_| and the bound callbacks. | 82 // Releases the |task_runner_| and the bound callbacks. |
| 61 void TearDown(); | 83 void TearDown(); |
| 62 | 84 |
| 63 // This posts a task onto the passed task runner which refreshes the list of | 85 // This posts a task onto the passed task runner which refreshes the list of |
| 64 // dump providers via the GetDumpProvidersFunction. If at least one dump | 86 // dump providers via the GetDumpProvidersFunction. If at least one dump |
| 65 // provider is available, this starts immediately polling on the task runner. | 87 // provider is available, this starts immediately polling on the task runner. |
| 66 // If not, the detector remains in the ENABLED state and will start polling | 88 // If not, the detector remains in the ENABLED state and will start polling |
| 67 // automatically (i.e. without requiring another call to Start()) on the | 89 // automatically (i.e. without requiring another call to Start()) on the |
| 68 // next call to NotifyMemoryDumpProvidersChanged(). | 90 // next call to NotifyMemoryDumpProvidersChanged(). |
| 69 void Start(); | 91 void Start(Config); |
| 70 | 92 |
| 71 // Stops the polling on the task runner (if was active at all). This doesn't | 93 // Stops the polling on the task runner (if was active at all). This doesn't |
| 72 // wait for the task runner to drain pending tasks, so it is possible that | 94 // wait for the task runner to drain pending tasks, so it is possible that |
| 73 // a polling will happen concurrently (or in the immediate future) with the | 95 // a polling will happen concurrently (or in the immediate future) with the |
| 74 // Stop() call. It is responsibility of the caller to drain or synchronize | 96 // Stop() call. It is responsibility of the caller to drain or synchronize |
| 75 // with the task runner. | 97 // with the task runner. |
| 76 void Stop(); | 98 void Stop(); |
| 77 | 99 |
| 100 // Clears the history of the peak detector, both for the sliding window and | |
| 101 // static threshold logic, if Start()-ed, otherwise it's a no-op. The intended | |
| 102 // use case is to prevent that a memory dump is triggered due to peak | |
| 103 // detection soon after another dump has been triggered for other reasons. | |
| 104 void Clear(); | |
| 105 | |
| 78 // Used by MemoryDumpManager to notify that the list of polling-capable dump | 106 // Used by MemoryDumpManager to notify that the list of polling-capable dump |
| 79 // providers has changed. The peak detector will reload the list on the next | 107 // providers has changed. The peak detector will reload the list on the next |
| 80 // polling task. This function can be called before Setup(), in which | 108 // polling task. This function can be called before Setup(), in which |
| 81 // case will be just a no-op. | 109 // case will be just a no-op. |
| 82 void NotifyMemoryDumpProvidersChanged(); | 110 void NotifyMemoryDumpProvidersChanged(); |
| 83 | 111 |
| 112 void SetStaticThresholdForTesting(uint64_t static_threshold_bytes); | |
| 113 | |
| 84 private: | 114 private: |
| 85 friend class MemoryPeakDetectorTest; | 115 friend class MemoryPeakDetectorTest; |
| 86 | 116 |
| 117 static constexpr uint32_t kSlidingWindowNumSamples = 50; | |
| 118 | |
| 87 MemoryPeakDetector(); | 119 MemoryPeakDetector(); |
| 88 ~MemoryPeakDetector(); | 120 ~MemoryPeakDetector(); |
| 89 | 121 |
| 90 // All these methods are always called on the |task_runner_|. | 122 // All these methods are always called on the |task_runner_|. |
| 91 void StartInternal(); | 123 void StartInternal(Config); |
| 92 void StopInternal(); | 124 void StopInternal(); |
| 93 void TearDownInternal(); | 125 void TearDownInternal(); |
| 94 void ReloadDumpProvidersAndStartPollingIfNeeded(); | 126 void ReloadDumpProvidersAndStartPollingIfNeeded(); |
| 95 void PollMemoryAndDetectPeak(uint32_t expected_generation); | 127 void PollMemoryAndDetectPeak(uint32_t expected_generation); |
| 128 bool DetectPeakUsingSlidingWindowStddev(uint64_t last_sample_bytes); | |
| 129 void ResetPollHistory(); | |
| 96 | 130 |
| 97 // It is safe to call these testing methods only on the |task_runner_|. | 131 // It is safe to call these testing methods only on the |task_runner_|. |
| 98 State state_for_testing() const { return state_; } | 132 State state_for_testing() const { return state_; } |
| 99 uint32_t poll_tasks_count_for_testing() const { | 133 uint32_t poll_tasks_count_for_testing() const { |
| 100 return poll_tasks_count_for_testing_; | 134 return poll_tasks_count_for_testing_; |
| 101 } | 135 } |
| 102 | 136 |
| 103 // The task runner where all the internal calls are posted onto. This field | 137 // The task runner where all the internal calls are posted onto. This field |
| 104 // must be NOT be accessed by the tasks posted on the |task_runner_| because | 138 // must be NOT be accessed by the tasks posted on the |task_runner_| because |
| 105 // there might still be outstanding tasks on the |task_runner_| while this | 139 // there might still be outstanding tasks on the |task_runner_| while this |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 120 DumpProvidersList dump_providers_; | 154 DumpProvidersList dump_providers_; |
| 121 | 155 |
| 122 // The generation is incremented every time the |state_| is changed and causes | 156 // The generation is incremented every time the |state_| is changed and causes |
| 123 // PollMemoryAndDetectPeak() to early out if the posted task doesn't match the | 157 // PollMemoryAndDetectPeak() to early out if the posted task doesn't match the |
| 124 // most recent |generation_|. This allows to drop on the floor outstanding | 158 // most recent |generation_|. This allows to drop on the floor outstanding |
| 125 // PostDelayedTask that refer to an old sequence that was later Stop()-ed or | 159 // PostDelayedTask that refer to an old sequence that was later Stop()-ed or |
| 126 // disabled because of NotifyMemoryDumpProvidersChanged(). | 160 // disabled because of NotifyMemoryDumpProvidersChanged(). |
| 127 uint32_t generation_; | 161 uint32_t generation_; |
| 128 | 162 |
| 129 State state_; | 163 State state_; |
| 130 uint32_t polling_interval_ms_; | 164 |
| 165 // Config passed to Start(), only valid when |state_| = {ENABLED, RUNNING}. | |
| 166 Config config_; | |
| 167 | |
| 168 int64_t static_threshold_bytes_; | |
| 169 uint32_t skip_polls_; | |
| 170 uint64_t last_dump_memory_total_; | |
| 171 uint64_t samples_bytes_[kSlidingWindowNumSamples]; | |
| 172 uint32_t samples_index_; | |
| 131 uint32_t poll_tasks_count_for_testing_; | 173 uint32_t poll_tasks_count_for_testing_; |
| 132 | 174 |
| 133 DISALLOW_COPY_AND_ASSIGN(MemoryPeakDetector); | 175 DISALLOW_COPY_AND_ASSIGN(MemoryPeakDetector); |
| 134 }; | 176 }; |
| 135 | 177 |
| 136 } // namespace trace_event | 178 } // namespace trace_event |
| 137 } // namespace base | 179 } // namespace base |
| 138 | 180 |
| 139 #endif // BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ | 181 #endif // BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ |
| OLD | NEW |