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