Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: base/trace_event/memory_peak_detector.h

Issue 2793023002: memory-infra: port peak detection logic to MemoryPeakDetector (Closed)
Patch Set: fix lambdas for MSVC Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 uint32_t polling_interval_ms;
52 uint32_t min_time_between_peaks_ms;
53 bool enable_verbose_poll_tracing;
ssid 2017/04/05 21:23:47 Nice to have some comment on the config members.
Primiano Tucci (use gerrit) 2017/04/06 20:07:10 done
54 };
55
42 static MemoryPeakDetector* GetInstance(); 56 static MemoryPeakDetector* GetInstance();
43 57
44 // Configures the peak detector, binding the polling tasks on the given 58 // Configures the peak detector, binding the polling tasks on the given
45 // thread. Setup() can be called several times, provided that: (1) Stop() 59 // 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 60 // is called; (2a) the previous task_runner is flushed or (2b) the task_runner
47 // remains the same. 61 // remains the same.
48 // GetDumpProvidersFunction: is the function that will be invoked to get 62 // GetDumpProvidersFunction: is the function that will be invoked to get
49 // an updated list of polling-capable dump providers. This is really just 63 // an updated list of polling-capable dump providers. This is really just
50 // MemoryDumpManager::GetDumpProvidersForPolling, but this extra level of 64 // MemoryDumpManager::GetDumpProvidersForPolling, but this extra level of
51 // indirection allows easier testing. 65 // indirection allows easier testing.
52 // SequencedTaskRunner: the task runner where PollMemoryAndDetectPeak() will 66 // SequencedTaskRunner: the task runner where PollMemoryAndDetectPeak() will
53 // be periodically called. 67 // be periodically called.
54 // OnPeakDetectedCallback: a callback that will be invoked on the 68 // OnPeakDetectedCallback: a callback that will be invoked on the
55 // given task runner when a memory peak is detected. 69 // given task runner when a memory peak is detected.
56 void Setup(const GetDumpProvidersFunction&, 70 void Setup(const GetDumpProvidersFunction&,
57 const scoped_refptr<SequencedTaskRunner>&, 71 const scoped_refptr<SequencedTaskRunner>&,
58 const OnPeakDetectedCallback&); 72 const OnPeakDetectedCallback&);
59 73
60 // Releases the |task_runner_| and the bound callbacks. 74 // Releases the |task_runner_| and the bound callbacks.
61 void TearDown(); 75 void TearDown();
62 76
63 // This posts a task onto the passed task runner which refreshes the list of 77 // 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 78 // dump providers via the GetDumpProvidersFunction. If at least one dump
65 // provider is available, this starts immediately polling on the task runner. 79 // 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 80 // 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 81 // automatically (i.e. without requiring another call to Start()) on the
68 // next call to NotifyMemoryDumpProvidersChanged(). 82 // next call to NotifyMemoryDumpProvidersChanged().
69 void Start(); 83 void Start(Config);
70 84
71 // Stops the polling on the task runner (if was active at all). This doesn't 85 // 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 86 // 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 87 // 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 88 // Stop() call. It is responsibility of the caller to drain or synchronize
75 // with the task runner. 89 // with the task runner.
76 void Stop(); 90 void Stop();
77 91
92 // Clears the history of the peak detector, both for the sliding window and
93 // static threshold logic, if Start()-ed, otherwise it's a no-op. The intended
94 // use case is to prevent that a memory dump is triggered due to peak
95 // detection soon after another dump has been triggered for other reasons.
96 void Clear();
ssid 2017/04/05 21:23:47 MemoryPeakDetector::Clear() sounds like this would
Primiano Tucci (use gerrit) 2017/04/06 20:07:10 But the comment says "If start()-ed, otherwise it'
ssid 2017/04/10 20:55:06 I tried to explain this in the comment below.
Primiano Tucci (use gerrit) 2017/04/11 11:12:09 See my other comment. That suggests to me that we
97
78 // Used by MemoryDumpManager to notify that the list of polling-capable dump 98 // 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 99 // 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 100 // polling task. This function can be called before Setup(), in which
81 // case will be just a no-op. 101 // case will be just a no-op.
82 void NotifyMemoryDumpProvidersChanged(); 102 void NotifyMemoryDumpProvidersChanged();
83 103
104 void SetStaticThresholdForTesting(uint64_t static_threshold_bytes);
105
84 private: 106 private:
85 friend class MemoryPeakDetectorTest; 107 friend class MemoryPeakDetectorTest;
86 108
109 static constexpr uint32_t kSlidingWindowNumSamples = 50;
110
87 MemoryPeakDetector(); 111 MemoryPeakDetector();
88 ~MemoryPeakDetector(); 112 ~MemoryPeakDetector();
89 113
90 // All these methods are always called on the |task_runner_|. 114 // All these methods are always called on the |task_runner_|.
91 void StartInternal(); 115 void StartInternal(Config);
92 void StopInternal(); 116 void StopInternal();
93 void TearDownInternal(); 117 void TearDownInternal();
94 void ReloadDumpProvidersAndStartPollingIfNeeded(); 118 void ReloadDumpProvidersAndStartPollingIfNeeded();
95 void PollMemoryAndDetectPeak(uint32_t expected_generation); 119 void PollMemoryAndDetectPeak(uint32_t expected_generation);
120 bool DetectPeakUsingSlidingWindowStddev(uint64_t last_sample_bytes);
121 void ResetPollHistory();
96 122
97 // It is safe to call these testing methods only on the |task_runner_|. 123 // It is safe to call these testing methods only on the |task_runner_|.
98 State state_for_testing() const { return state_; } 124 State state_for_testing() const { return state_; }
99 uint32_t poll_tasks_count_for_testing() const { 125 uint32_t poll_tasks_count_for_testing() const {
100 return poll_tasks_count_for_testing_; 126 return poll_tasks_count_for_testing_;
101 } 127 }
102 128
103 // The task runner where all the internal calls are posted onto. This field 129 // 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 130 // 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 131 // there might still be outstanding tasks on the |task_runner_| while this
(...skipping 14 matching lines...) Expand all
120 DumpProvidersList dump_providers_; 146 DumpProvidersList dump_providers_;
121 147
122 // The generation is incremented every time the |state_| is changed and causes 148 // 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 149 // PollMemoryAndDetectPeak() to early out if the posted task doesn't match the
124 // most recent |generation_|. This allows to drop on the floor outstanding 150 // 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 151 // PostDelayedTask that refer to an old sequence that was later Stop()-ed or
126 // disabled because of NotifyMemoryDumpProvidersChanged(). 152 // disabled because of NotifyMemoryDumpProvidersChanged().
127 uint32_t generation_; 153 uint32_t generation_;
128 154
129 State state_; 155 State state_;
130 uint32_t polling_interval_ms_; 156
157 // Config passed to Start(), only valid when |state_| = {ENABLED, RUNNING}.
158 Config config_;
159
160 int64_t static_threshold_bytes_;
161 uint32_t skip_polls_;
162 uint64_t last_dump_memory_total_;
163 uint64_t samples_bytes_[kSlidingWindowNumSamples];
ssid 2017/04/05 21:23:47 Samples were stored in kb because of the overflows
Primiano Tucci (use gerrit) 2017/04/06 20:07:10 I moved the stddev to floats, should be fine now.
164 uint32_t samples_index_;
131 uint32_t poll_tasks_count_for_testing_; 165 uint32_t poll_tasks_count_for_testing_;
132 166
133 DISALLOW_COPY_AND_ASSIGN(MemoryPeakDetector); 167 DISALLOW_COPY_AND_ASSIGN(MemoryPeakDetector);
134 }; 168 };
135 169
136 } // namespace trace_event 170 } // namespace trace_event
137 } // namespace base 171 } // namespace base
138 172
139 #endif // BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ 173 #endif // BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_
OLDNEW
« no previous file with comments | « no previous file | base/trace_event/memory_peak_detector.cc » ('j') | base/trace_event/memory_peak_detector.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698