• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H
6 #define BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H
7 
8 #include <memory>
9 
10 #include "base/base_export.h"
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/timer/timer.h"
14 #include "base/trace_event/memory_dump_request_args.h"
15 
16 namespace base {
17 class SingleThreadTaskRunner;
18 
19 namespace trace_event {
20 
21 class MemoryDumpManager;
22 
23 // Schedules global dump requests based on the triggers added. The methods of
24 // this class are NOT thread safe and the client has to take care of invoking
25 // all the methods of the class safely.
26 class BASE_EXPORT MemoryDumpScheduler {
27  public:
28   static MemoryDumpScheduler* GetInstance();
29 
30   // Initializes the scheduler. NOT thread safe.
31   void Setup(MemoryDumpManager* mdm_,
32              scoped_refptr<SingleThreadTaskRunner> polling_task_runner);
33 
34   // Adds triggers for scheduling global dumps. Both periodic and peak triggers
35   // cannot be added together. At the moment the periodic support is limited to
36   // at most one periodic trigger per dump mode and peak triggers are limited to
37   // at most one. All intervals should be an integeral multiple of the smallest
38   // interval specified. NOT thread safe.
39   void AddTrigger(MemoryDumpType trigger_type,
40                   MemoryDumpLevelOfDetail level_of_detail,
41                   uint32_t min_time_between_dumps_ms);
42 
43   // Starts periodic dumps. NOT thread safe and triggers must be added before
44   // enabling.
45   void EnablePeriodicTriggerIfNeeded();
46 
47   // Starts polling memory total. NOT thread safe and triggers must be added
48   // before enabling.
49   void EnablePollingIfNeeded();
50 
51   // Resets time for triggering dump to account for minimum time between the
52   // dumps. NOT thread safe.
53   void NotifyDumpTriggered();
54 
55   // Disables all triggers. NOT thread safe. This should be called before
56   // polling thread is stopped to stop polling cleanly.
57   void DisableAllTriggers();
58 
59  private:
60   friend class MemoryDumpManagerTest;
61   friend class MemoryDumpSchedulerPollingTest;
62   FRIEND_TEST_ALL_PREFIXES(MemoryDumpManagerTest, TestPollingOnDumpThread);
63   FRIEND_TEST_ALL_PREFIXES(MemoryDumpSchedulerPollingTest, NotifyDumpTriggered);
64 
65   // Helper class to schdule periodic memory dumps.
66   struct BASE_EXPORT PeriodicTriggerState {
67     PeriodicTriggerState();
68     ~PeriodicTriggerState();
69 
70     bool is_configured;
71 
72     RepeatingTimer timer;
73     uint32_t dump_count;
74     uint32_t min_timer_period_ms;
75     uint32_t light_dumps_rate;
76     uint32_t heavy_dumps_rate;
77 
78     uint32_t light_dump_period_ms;
79     uint32_t heavy_dump_period_ms;
80 
81     DISALLOW_COPY_AND_ASSIGN(PeriodicTriggerState);
82   };
83 
84   struct BASE_EXPORT PollingTriggerState {
85     enum State {
86       CONFIGURED,  // Polling trigger was added.
87       ENABLED,     // Polling is running.
88       DISABLED     // Polling is disabled.
89     };
90 
91     static const uint32_t kMaxNumMemorySamples = 50;
92 
93     PollingTriggerState();
94     ~PollingTriggerState();
95 
96     // Helper to clear the tracked memory totals and poll count from last dump.
97     void ResetTotals();
98 
99     State current_state;
100     MemoryDumpLevelOfDetail level_of_detail;
101 
102     uint32_t polling_interval_ms;
103 
104     // Minimum numer of polls after the last dump at which next dump can be
105     // triggered.
106     int min_polls_between_dumps;
107     int num_polls_from_last_dump;
108 
109     uint64_t last_dump_memory_total;
110     int64_t memory_increase_threshold;
111     uint64_t last_memory_totals_kb[kMaxNumMemorySamples];
112     uint32_t last_memory_totals_kb_index;
113 
114     DISALLOW_COPY_AND_ASSIGN(PollingTriggerState);
115   };
116 
117   MemoryDumpScheduler();
118   ~MemoryDumpScheduler();
119 
120   // Helper to set polling disabled.
121   void DisablePollingOnPollingThread();
122 
123   // Periodically called by the timer.
124   void RequestPeriodicGlobalDump();
125 
126   // Called for polling memory usage and trigger dumps if peak is detected.
127   void PollMemoryOnPollingThread();
128 
129   // Returns true if peak memory value is detected.
130   bool ShouldTriggerDump(uint64_t current_memory_total);
131 
132   // Helper to detect peaks in memory usage.
133   bool IsCurrentSamplePeak(uint64_t current_memory_total);
134 
135   // Must be set before enabling tracing.
136   static void SetPollingIntervalForTesting(uint32_t interval);
137 
138   // True if periodic dumping is enabled.
139   bool IsPeriodicTimerRunningForTesting();
140 
141   MemoryDumpManager* mdm_;
142 
143   // Accessed on the thread of the client before enabling and only accessed on
144   // the thread that called "EnablePeriodicTriggersIfNeeded()" after enabling.
145   std::unique_ptr<PeriodicTriggerState> periodic_state_;
146 
147   // Accessed on the thread of the client before enabling and only accessed on
148   // the polling thread after enabling.
149   std::unique_ptr<PollingTriggerState> polling_state_;
150 
151   // Accessed on the thread of the client only.
152   scoped_refptr<SingleThreadTaskRunner> polling_task_runner_;
153 
154   // True when the scheduler is setup. Accessed on the thread of client only.
155   bool is_setup_;
156 
157   DISALLOW_COPY_AND_ASSIGN(MemoryDumpScheduler);
158 };
159 
160 }  // namespace trace_event
161 }  // namespace base
162 
163 #endif  // BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H
164