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

Side by Side Diff: base/trace_event/memory_dump_manager.cc

Issue 1267963002: [tracing] Throttle rate of heavy dumps and support to request light/heavy dumps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@light_dumps
Patch Set: Fix win build. Created 5 years, 4 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "base/trace_event/memory_dump_manager.h" 5 #include "base/trace_event/memory_dump_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 25 matching lines...) Expand all
36 namespace base { 36 namespace base {
37 namespace trace_event { 37 namespace trace_event {
38 38
39 namespace { 39 namespace {
40 40
41 // TODO(primiano): this should be smarter and should do something similar to 41 // TODO(primiano): this should be smarter and should do something similar to
42 // trace event synthetic delays. 42 // trace event synthetic delays.
43 const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra"); 43 const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra");
44 44
45 // Throttle mmaps at a rate of once every kHeavyMmapsDumpsRate standard dumps. 45 // Throttle mmaps at a rate of once every kHeavyMmapsDumpsRate standard dumps.
46 const int kHeavyMmapsDumpsRate = 8; // 250 ms * 8 = 2000 ms. 46 const int kHeavyDumpsRate = 8; // 250 ms * 8 = 2000 ms.
47 const int kDumpIntervalMs = 250; 47 const int kDumpIntervalMs = 250;
48 const int kTraceEventNumArgs = 1; 48 const int kTraceEventNumArgs = 1;
49 const char* kTraceEventArgNames[] = {"dumps"}; 49 const char* kTraceEventArgNames[] = {"dumps"};
50 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; 50 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
51 51
52 StaticAtomicSequenceNumber g_next_guid; 52 StaticAtomicSequenceNumber g_next_guid;
53 uint32 g_periodic_dumps_count = 0; 53 uint32 g_periodic_dumps_count = 0;
54 MemoryDumpManager* g_instance_for_testing = nullptr; 54 MemoryDumpManager* g_instance_for_testing = nullptr;
55 MemoryDumpProvider* g_mmaps_dump_provider = nullptr;
56 55
57 void RequestPeriodicGlobalDump() { 56 void RequestPeriodicGlobalDump() {
58 MemoryDumpType dump_type = g_periodic_dumps_count == 0 57 MemoryDumpArgs::LevelOfDetail dump_level_of_detail =
59 ? MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS 58 g_periodic_dumps_count == 0 ? MemoryDumpArgs::LEVEL_OF_DETAIL_HIGH
60 : MemoryDumpType::PERIODIC_INTERVAL; 59 : MemoryDumpArgs::LEVEL_OF_DETAIL_LOW;
61 if (++g_periodic_dumps_count == kHeavyMmapsDumpsRate) 60 if (++g_periodic_dumps_count == kHeavyDumpsRate)
62 g_periodic_dumps_count = 0; 61 g_periodic_dumps_count = 0;
63 62
64 MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type); 63 MemoryDumpArgs dump_args = {dump_level_of_detail};
64 MemoryDumpManager::GetInstance()->RequestGlobalDump(
65 MemoryDumpType::PERIODIC_INTERVAL, dump_args);
65 } 66 }
66 67
67 } // namespace 68 } // namespace
68 69
69 // static 70 // static
70 const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory; 71 const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory;
71 72
72 // static 73 // static
73 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; 74 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3;
74 75
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 112
112 if (skip_core_dumpers_auto_registration_for_testing_) 113 if (skip_core_dumpers_auto_registration_for_testing_)
113 return; 114 return;
114 115
115 // Enable the core dump providers. 116 // Enable the core dump providers.
116 #if !defined(OS_NACL) 117 #if !defined(OS_NACL)
117 RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance()); 118 RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
118 #endif 119 #endif
119 120
120 #if defined(OS_LINUX) || defined(OS_ANDROID) 121 #if defined(OS_LINUX) || defined(OS_ANDROID)
121 g_mmaps_dump_provider = ProcessMemoryMapsDumpProvider::GetInstance(); 122 RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance());
122 RegisterDumpProvider(g_mmaps_dump_provider);
123 RegisterDumpProvider(MallocDumpProvider::GetInstance()); 123 RegisterDumpProvider(MallocDumpProvider::GetInstance());
124 system_allocator_pool_name_ = MallocDumpProvider::kAllocatedObjects; 124 system_allocator_pool_name_ = MallocDumpProvider::kAllocatedObjects;
125 #endif 125 #endif
126 126
127 #if defined(OS_ANDROID) 127 #if defined(OS_ANDROID)
128 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance()); 128 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance());
129 #endif 129 #endif
130 130
131 #if defined(OS_WIN) 131 #if defined(OS_WIN)
132 RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); 132 RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 DCHECK_IMPLIES( 173 DCHECK_IMPLIES(
174 subtle::NoBarrier_Load(&memory_tracing_enabled_), 174 subtle::NoBarrier_Load(&memory_tracing_enabled_),
175 mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread()) 175 mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread())
176 << "The MemoryDumpProvider attempted to unregister itself in a racy way. " 176 << "The MemoryDumpProvider attempted to unregister itself in a racy way. "
177 << "Please file a crbug."; 177 << "Please file a crbug.";
178 178
179 dump_providers_.erase(mdp_iter); 179 dump_providers_.erase(mdp_iter);
180 did_unregister_dump_provider_ = true; 180 did_unregister_dump_provider_ = true;
181 } 181 }
182 182
183 void MemoryDumpManager::RequestGlobalDump( 183 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type,
184 MemoryDumpType dump_type, 184 const MemoryDumpArgs& dump_args,
185 const MemoryDumpCallback& callback) { 185 const MemoryDumpCallback& callback) {
186 // Bail out immediately if tracing is not enabled at all. 186 // Bail out immediately if tracing is not enabled at all.
187 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) { 187 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) {
188 if (!callback.is_null()) 188 if (!callback.is_null())
189 callback.Run(0u /* guid */, false /* success */); 189 callback.Run(0u /* guid */, false /* success */);
190 return; 190 return;
191 } 191 }
192 192
193 const uint64 guid = 193 const uint64 guid =
194 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); 194 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());
195 195
196 // The delegate_ is supposed to be thread safe, immutable and long lived. 196 // The delegate_ is supposed to be thread safe, immutable and long lived.
197 // No need to keep the lock after we ensure that a delegate has been set. 197 // No need to keep the lock after we ensure that a delegate has been set.
198 MemoryDumpManagerDelegate* delegate; 198 MemoryDumpManagerDelegate* delegate;
199 { 199 {
200 AutoLock lock(lock_); 200 AutoLock lock(lock_);
201 delegate = delegate_; 201 delegate = delegate_;
202 } 202 }
203 203
204 if (delegate) { 204 if (delegate) {
205 // The delegate is in charge to coordinate the request among all the 205 // The delegate is in charge to coordinate the request among all the
206 // processes and call the CreateLocalDumpPoint on the local process. 206 // processes and call the CreateLocalDumpPoint on the local process.
207 MemoryDumpRequestArgs args = {guid, dump_type}; 207 MemoryDumpRequestArgs args = {guid, dump_type, dump_args};
208 delegate->RequestGlobalMemoryDump(args, callback); 208 delegate->RequestGlobalMemoryDump(args, callback);
209 } else if (!callback.is_null()) { 209 } else if (!callback.is_null()) {
210 callback.Run(guid, false /* success */); 210 callback.Run(guid, false /* success */);
211 } 211 }
212 } 212 }
213 213
214 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) { 214 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type,
215 RequestGlobalDump(dump_type, MemoryDumpCallback()); 215 const MemoryDumpArgs& dump_args) {
216 RequestGlobalDump(dump_type, dump_args, MemoryDumpCallback());
216 } 217 }
217 218
218 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, 219 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
219 const MemoryDumpCallback& callback) { 220 const MemoryDumpCallback& callback) {
220 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; 221 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state;
221 { 222 {
222 AutoLock lock(lock_); 223 AutoLock lock(lock_);
223 did_unregister_dump_provider_ = false; 224 did_unregister_dump_provider_ = false;
224 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( 225 pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
225 args, dump_providers_.begin(), session_state_, callback)); 226 args, dump_providers_.begin(), session_state_, callback));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 if (did_unregister_dump_provider_) { 267 if (did_unregister_dump_provider_) {
267 return AbortDumpLocked(pmd_async_state->callback, 268 return AbortDumpLocked(pmd_async_state->callback,
268 pmd_async_state->task_runner, 269 pmd_async_state->task_runner,
269 pmd_async_state->req_args.dump_guid); 270 pmd_async_state->req_args.dump_guid);
270 } 271 }
271 272
272 auto* mdp_info = &*pmd_async_state->next_dump_provider; 273 auto* mdp_info = &*pmd_async_state->next_dump_provider;
273 mdp = mdp_info->dump_provider; 274 mdp = mdp_info->dump_provider;
274 if (mdp_info->disabled) { 275 if (mdp_info->disabled) {
275 skip_dump = true; 276 skip_dump = true;
276 } else if (mdp == g_mmaps_dump_provider &&
277 pmd_async_state->req_args.dump_type !=
278 MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS &&
279 pmd_async_state->req_args.dump_type !=
280 MemoryDumpType::EXPLICITLY_TRIGGERED) {
281 // Mmaps dumping is very heavyweight and cannot be performed at the same
282 // rate of other dumps. TODO(primiano): this is a hack and should be
283 // cleaned up as part of crbug.com/499731.
284 skip_dump = true;
285 } else if (mdp_info->task_runner && 277 } else if (mdp_info->task_runner &&
286 !mdp_info->task_runner->BelongsToCurrentThread()) { 278 !mdp_info->task_runner->BelongsToCurrentThread()) {
287 // It's time to hop onto another thread. 279 // It's time to hop onto another thread.
288 280
289 // Copy the callback + arguments just for the unlikley case in which 281 // Copy the callback + arguments just for the unlikley case in which
290 // PostTask fails. In such case the Bind helper will destroy the 282 // PostTask fails. In such case the Bind helper will destroy the
291 // pmd_async_state and we must keep a copy of the fields to notify the 283 // pmd_async_state and we must keep a copy of the fields to notify the
292 // abort. 284 // abort.
293 MemoryDumpCallback callback = pmd_async_state->callback; 285 MemoryDumpCallback callback = pmd_async_state->callback;
294 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = 286 scoped_refptr<SingleThreadTaskRunner> callback_task_runner =
(...skipping 10 matching lines...) Expand all
305 // disable the dump provider and abort this dump. 297 // disable the dump provider and abort this dump.
306 mdp_info->disabled = true; 298 mdp_info->disabled = true;
307 return AbortDumpLocked(callback, callback_task_runner, dump_guid); 299 return AbortDumpLocked(callback, callback_task_runner, dump_guid);
308 } 300 }
309 } // AutoLock(lock_) 301 } // AutoLock(lock_)
310 302
311 // Invoke the dump provider without holding the |lock_|. 303 // Invoke the dump provider without holding the |lock_|.
312 bool finalize = false; 304 bool finalize = false;
313 bool dump_successful = false; 305 bool dump_successful = false;
314 306
315 // TODO(ssid): Change RequestGlobalDump to use MemoryDumpArgs along with
316 // MemoryDumpType to get request for light / heavy dump, and remove this
317 // constant.
318 if (!skip_dump) { 307 if (!skip_dump) {
319 MemoryDumpArgs dump_args = {MemoryDumpArgs::LEVEL_OF_DETAIL_HIGH}; 308 dump_successful = mdp->OnMemoryDump(pmd_async_state->req_args.dump_args,
320 dump_successful = 309 &pmd_async_state->process_memory_dump);
321 mdp->OnMemoryDump(dump_args, &pmd_async_state->process_memory_dump);
322 } 310 }
323 311
324 { 312 {
325 AutoLock lock(lock_); 313 AutoLock lock(lock_);
326 if (did_unregister_dump_provider_) { 314 if (did_unregister_dump_provider_) {
327 return AbortDumpLocked(pmd_async_state->callback, 315 return AbortDumpLocked(pmd_async_state->callback,
328 pmd_async_state->task_runner, 316 pmd_async_state->task_runner,
329 pmd_async_state->req_args.dump_guid); 317 pmd_async_state->req_args.dump_guid);
330 } 318 }
331 auto* mdp_info = &*pmd_async_state->next_dump_provider; 319 auto* mdp_info = &*pmd_async_state->next_dump_provider;
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 next_dump_provider(next_dump_provider), 470 next_dump_provider(next_dump_provider),
483 callback(callback), 471 callback(callback),
484 task_runner(MessageLoop::current()->task_runner()) { 472 task_runner(MessageLoop::current()->task_runner()) {
485 } 473 }
486 474
487 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { 475 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() {
488 } 476 }
489 477
490 } // namespace trace_event 478 } // namespace trace_event
491 } // namespace base 479 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/memory_dump_manager.h ('k') | base/trace_event/memory_dump_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698