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

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

Issue 2799023002: memory-infra: Switch to MemoryPeakDetector and simplify MemoryDumpScheduler (Closed)
Patch Set: . 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 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 <inttypes.h> 7 #include <inttypes.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 16 matching lines...) Expand all
27 #include "base/trace_event/heap_profiler.h" 27 #include "base/trace_event/heap_profiler.h"
28 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" 28 #include "base/trace_event/heap_profiler_allocation_context_tracker.h"
29 #include "base/trace_event/heap_profiler_event_filter.h" 29 #include "base/trace_event/heap_profiler_event_filter.h"
30 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" 30 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
31 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" 31 #include "base/trace_event/heap_profiler_type_name_deduplicator.h"
32 #include "base/trace_event/malloc_dump_provider.h" 32 #include "base/trace_event/malloc_dump_provider.h"
33 #include "base/trace_event/memory_dump_provider.h" 33 #include "base/trace_event/memory_dump_provider.h"
34 #include "base/trace_event/memory_dump_scheduler.h" 34 #include "base/trace_event/memory_dump_scheduler.h"
35 #include "base/trace_event/memory_dump_session_state.h" 35 #include "base/trace_event/memory_dump_session_state.h"
36 #include "base/trace_event/memory_infra_background_whitelist.h" 36 #include "base/trace_event/memory_infra_background_whitelist.h"
37 #include "base/trace_event/memory_peak_detector.h"
37 #include "base/trace_event/process_memory_dump.h" 38 #include "base/trace_event/process_memory_dump.h"
38 #include "base/trace_event/trace_event.h" 39 #include "base/trace_event/trace_event.h"
39 #include "base/trace_event/trace_event_argument.h" 40 #include "base/trace_event/trace_event_argument.h"
40 #include "build/build_config.h" 41 #include "build/build_config.h"
41 42
42 #if defined(OS_ANDROID) 43 #if defined(OS_ANDROID)
43 #include "base/trace_event/java_heap_dump_provider_android.h" 44 #include "base/trace_event/java_heap_dump_provider_android.h"
44 #endif 45 #endif
45 46
46 namespace base { 47 namespace base {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 void EstimateTraceMemoryOverhead( 119 void EstimateTraceMemoryOverhead(
119 TraceEventMemoryOverhead* overhead) override { 120 TraceEventMemoryOverhead* overhead) override {
120 return (session_state.get()->*getter_function)() 121 return (session_state.get()->*getter_function)()
121 ->EstimateTraceMemoryOverhead(overhead); 122 ->EstimateTraceMemoryOverhead(overhead);
122 } 123 }
123 124
124 scoped_refptr<MemoryDumpSessionState> session_state; 125 scoped_refptr<MemoryDumpSessionState> session_state;
125 GetterFunctPtr const getter_function; 126 GetterFunctPtr const getter_function;
126 }; 127 };
127 128
129 void OnPeakDetected(MemoryDumpLevelOfDetail level_of_detail) {
130 MemoryDumpManager::GetInstance()->RequestGlobalDump(
131 MemoryDumpType::PEAK_MEMORY_USAGE, level_of_detail);
132 }
133
128 } // namespace 134 } // namespace
129 135
130 // static 136 // static
131 const char* const MemoryDumpManager::kTraceCategory = 137 const char* const MemoryDumpManager::kTraceCategory =
132 TRACE_DISABLED_BY_DEFAULT("memory-infra"); 138 TRACE_DISABLED_BY_DEFAULT("memory-infra");
133 139
134 // static 140 // static
135 const char* const MemoryDumpManager::kLogPrefix = "Memory-infra dump"; 141 const char* const MemoryDumpManager::kLogPrefix = "Memory-infra dump";
136 142
137 // static 143 // static
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 } 335 }
330 336
331 { 337 {
332 AutoLock lock(lock_); 338 AutoLock lock(lock_);
333 bool already_registered = !dump_providers_.insert(mdpinfo).second; 339 bool already_registered = !dump_providers_.insert(mdpinfo).second;
334 // This actually happens in some tests which don't have a clean tear-down 340 // This actually happens in some tests which don't have a clean tear-down
335 // path for RenderThreadImpl::Init(). 341 // path for RenderThreadImpl::Init().
336 if (already_registered) 342 if (already_registered)
337 return; 343 return;
338 344
339 // The list of polling MDPs is populated OnTraceLogEnabled(). This code 345 if (options.is_fast_polling_supported)
340 // deals with the case of a MDP capable of fast polling that is registered 346 MemoryPeakDetector::GetInstance()->NotifyMemoryDumpProvidersChanged();
341 // after the OnTraceLogEnabled()
342 if (options.is_fast_polling_supported && dump_thread_) {
343 dump_thread_->task_runner()->PostTask(
344 FROM_HERE, Bind(&MemoryDumpManager::RegisterPollingMDPOnDumpThread,
345 Unretained(this), mdpinfo));
346 }
347 } 347 }
348 348
349 if (heap_profiling_enabled_) 349 if (heap_profiling_enabled_)
350 mdp->OnHeapProfilingEnabled(true); 350 mdp->OnHeapProfilingEnabled(true);
351 } 351 }
352 352
353 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { 353 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
354 UnregisterDumpProviderInternal(mdp, false /* delete_async */); 354 UnregisterDumpProviderInternal(mdp, false /* delete_async */);
355 } 355 }
356 356
(...skipping 18 matching lines...) Expand all
375 } 375 }
376 376
377 if (mdp_iter == dump_providers_.end()) 377 if (mdp_iter == dump_providers_.end())
378 return; // Not registered / already unregistered. 378 return; // Not registered / already unregistered.
379 379
380 if (take_mdp_ownership_and_delete_async) { 380 if (take_mdp_ownership_and_delete_async) {
381 // The MDP will be deleted whenever the MDPInfo struct will, that is either: 381 // The MDP will be deleted whenever the MDPInfo struct will, that is either:
382 // - At the end of this function, if no dump is in progress. 382 // - At the end of this function, if no dump is in progress.
383 // - Either in SetupNextMemoryDump() or InvokeOnMemoryDump() when MDPInfo is 383 // - Either in SetupNextMemoryDump() or InvokeOnMemoryDump() when MDPInfo is
384 // removed from |pending_dump_providers|. 384 // removed from |pending_dump_providers|.
385 // - When the provider is removed from |dump_providers_for_polling_|. 385 // - When the provider is removed from other clients (MemoryPeakDetector).
386 DCHECK(!(*mdp_iter)->owned_dump_provider); 386 DCHECK(!(*mdp_iter)->owned_dump_provider);
387 (*mdp_iter)->owned_dump_provider = std::move(owned_mdp); 387 (*mdp_iter)->owned_dump_provider = std::move(owned_mdp);
388 } else if (strict_thread_check_blacklist_.count((*mdp_iter)->name) == 0 || 388 } else if (strict_thread_check_blacklist_.count((*mdp_iter)->name) == 0 ||
389 subtle::NoBarrier_Load(&memory_tracing_enabled_)) { 389 subtle::NoBarrier_Load(&memory_tracing_enabled_)) {
390 // If dump provider's name is on |strict_thread_check_blacklist_|, then the 390 // If dump provider's name is on |strict_thread_check_blacklist_|, then the
391 // DCHECK is fired only when tracing is enabled. Otherwise the DCHECK is 391 // DCHECK is fired only when tracing is enabled. Otherwise the DCHECK is
392 // fired even when tracing is not enabled (stricter). 392 // fired even when tracing is not enabled (stricter).
393 // TODO(ssid): Remove this condition after removing all the dump providers 393 // TODO(ssid): Remove this condition after removing all the dump providers
394 // in the blacklist and the buildbots are no longer flakily hitting the 394 // in the blacklist and the buildbots are no longer flakily hitting the
395 // DCHECK, crbug.com/643438. 395 // DCHECK, crbug.com/643438.
396 396
397 // If you hit this DCHECK, your dump provider has a bug. 397 // If you hit this DCHECK, your dump provider has a bug.
398 // Unregistration of a MemoryDumpProvider is safe only if: 398 // Unregistration of a MemoryDumpProvider is safe only if:
399 // - The MDP has specified a sequenced task runner affinity AND the 399 // - The MDP has specified a sequenced task runner affinity AND the
400 // unregistration happens on the same task runner. So that the MDP cannot 400 // unregistration happens on the same task runner. So that the MDP cannot
401 // unregister and be in the middle of a OnMemoryDump() at the same time. 401 // unregister and be in the middle of a OnMemoryDump() at the same time.
402 // - The MDP has NOT specified a task runner affinity and its ownership is 402 // - The MDP has NOT specified a task runner affinity and its ownership is
403 // transferred via UnregisterAndDeleteDumpProviderSoon(). 403 // transferred via UnregisterAndDeleteDumpProviderSoon().
404 // In all the other cases, it is not possible to guarantee that the 404 // In all the other cases, it is not possible to guarantee that the
405 // unregistration will not race with OnMemoryDump() calls. 405 // unregistration will not race with OnMemoryDump() calls.
406 DCHECK((*mdp_iter)->task_runner && 406 DCHECK((*mdp_iter)->task_runner &&
407 (*mdp_iter)->task_runner->RunsTasksOnCurrentThread()) 407 (*mdp_iter)->task_runner->RunsTasksOnCurrentThread())
408 << "MemoryDumpProvider \"" << (*mdp_iter)->name << "\" attempted to " 408 << "MemoryDumpProvider \"" << (*mdp_iter)->name << "\" attempted to "
409 << "unregister itself in a racy way. Please file a crbug."; 409 << "unregister itself in a racy way. Please file a crbug.";
410 } 410 }
411 411
412 if ((*mdp_iter)->options.is_fast_polling_supported && dump_thread_) { 412 if ((*mdp_iter)->options.is_fast_polling_supported) {
413 DCHECK(take_mdp_ownership_and_delete_async); 413 DCHECK(take_mdp_ownership_and_delete_async);
414 dump_thread_->task_runner()->PostTask( 414 MemoryPeakDetector::GetInstance()->NotifyMemoryDumpProvidersChanged();
415 FROM_HERE, Bind(&MemoryDumpManager::UnregisterPollingMDPOnDumpThread,
416 Unretained(this), *mdp_iter));
417 } 415 }
418 416
419 // The MDPInfo instance can still be referenced by the 417 // The MDPInfo instance can still be referenced by the
420 // |ProcessMemoryDumpAsyncState.pending_dump_providers|. For this reason 418 // |ProcessMemoryDumpAsyncState.pending_dump_providers|. For this reason
421 // the MDPInfo is flagged as disabled. It will cause InvokeOnMemoryDump() 419 // the MDPInfo is flagged as disabled. It will cause InvokeOnMemoryDump()
422 // to just skip it, without actually invoking the |mdp|, which might be 420 // to just skip it, without actually invoking the |mdp|, which might be
423 // destroyed by the caller soon after this method returns. 421 // destroyed by the caller soon after this method returns.
424 (*mdp_iter)->disabled = true; 422 (*mdp_iter)->disabled = true;
425 dump_providers_.erase(mdp_iter); 423 dump_providers_.erase(mdp_iter);
426 } 424 }
427 425
428 void MemoryDumpManager::RegisterPollingMDPOnDumpThread(
429 scoped_refptr<MemoryDumpProviderInfo> mdpinfo) {
430 AutoLock lock(lock_);
431 dump_providers_for_polling_.insert(mdpinfo);
432
433 // Notify ready for polling when first polling supported provider is
434 // registered. This handles the case where OnTraceLogEnabled() did not notify
435 // ready since no polling supported mdp has yet been registered.
436 if (dump_providers_for_polling_.size() == 1)
437 MemoryDumpScheduler::GetInstance()->EnablePollingIfNeeded();
438 }
439
440 void MemoryDumpManager::UnregisterPollingMDPOnDumpThread(
441 scoped_refptr<MemoryDumpProviderInfo> mdpinfo) {
442 mdpinfo->dump_provider->SuspendFastMemoryPolling();
443
444 AutoLock lock(lock_);
445 dump_providers_for_polling_.erase(mdpinfo);
446 DCHECK(!dump_providers_for_polling_.empty())
447 << "All polling MDPs cannot be unregistered.";
448 }
449
450 void MemoryDumpManager::RequestGlobalDump( 426 void MemoryDumpManager::RequestGlobalDump(
451 MemoryDumpType dump_type, 427 MemoryDumpType dump_type,
452 MemoryDumpLevelOfDetail level_of_detail, 428 MemoryDumpLevelOfDetail level_of_detail,
453 const MemoryDumpCallback& callback) { 429 const MemoryDumpCallback& callback) {
454 // Bail out immediately if tracing is not enabled at all or if the dump mode 430 // Bail out immediately if tracing is not enabled at all or if the dump mode
455 // is not allowed. 431 // is not allowed.
456 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) || 432 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) ||
457 !IsDumpModeAllowed(level_of_detail)) { 433 !IsDumpModeAllowed(level_of_detail)) {
458 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory 434 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory
459 << " tracing category is not enabled or the requested dump mode is " 435 << " tracing category is not enabled or the requested dump mode is "
(...skipping 14 matching lines...) Expand all
474 MemoryDumpTypeToString(dump_type), "level_of_detail", 450 MemoryDumpTypeToString(dump_type), "level_of_detail",
475 MemoryDumpLevelOfDetailToString(level_of_detail)); 451 MemoryDumpLevelOfDetailToString(level_of_detail));
476 MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); 452 MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback);
477 453
478 // The delegate will coordinate the IPC broadcast and at some point invoke 454 // The delegate will coordinate the IPC broadcast and at some point invoke
479 // CreateProcessDump() to get a dump for the current process. 455 // CreateProcessDump() to get a dump for the current process.
480 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; 456 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail};
481 delegate_->RequestGlobalMemoryDump(args, wrapped_callback); 457 delegate_->RequestGlobalMemoryDump(args, wrapped_callback);
482 } 458 }
483 459
460 void MemoryDumpManager::GetDumpProvidersForPolling(
461 std::vector<scoped_refptr<MemoryDumpProviderInfo>>* providers) {
462 AutoLock lock(lock_);
463 for (const scoped_refptr<MemoryDumpProviderInfo>& mdp : dump_providers_) {
hjd 2017/04/06 12:14:17 We could DCHECK providers is empty or use a set so
Primiano Tucci (use gerrit) 2017/04/10 19:16:41 Good point. done.
464 if (mdp->options.is_fast_polling_supported)
465 providers->push_back(mdp);
466 }
467 }
468
484 void MemoryDumpManager::RequestGlobalDump( 469 void MemoryDumpManager::RequestGlobalDump(
485 MemoryDumpType dump_type, 470 MemoryDumpType dump_type,
486 MemoryDumpLevelOfDetail level_of_detail) { 471 MemoryDumpLevelOfDetail level_of_detail) {
487 RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback()); 472 RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback());
488 } 473 }
489 474
490 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( 475 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting(
491 MemoryDumpProvider* provider) { 476 MemoryDumpProvider* provider) {
492 AutoLock lock(lock_); 477 AutoLock lock(lock_);
493 478
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( 511 pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
527 args, dump_providers_, session_state_, callback, 512 args, dump_providers_, session_state_, callback,
528 dump_thread_ ? dump_thread_->task_runner() : nullptr)); 513 dump_thread_ ? dump_thread_->task_runner() : nullptr));
529 514
530 // Safety check to prevent reaching here without calling RequestGlobalDump, 515 // Safety check to prevent reaching here without calling RequestGlobalDump,
531 // with disallowed modes. If |session_state_| is null then tracing is 516 // with disallowed modes. If |session_state_| is null then tracing is
532 // disabled. 517 // disabled.
533 CHECK(!session_state_ || 518 CHECK(!session_state_ ||
534 session_state_->IsDumpModeAllowed(args.level_of_detail)); 519 session_state_->IsDumpModeAllowed(args.level_of_detail));
535 520
536 MemoryDumpScheduler::GetInstance()->NotifyDumpTriggered(); 521 // If enabled, holds back the peak detector resetting its estimation window.
522 MemoryPeakDetector::GetInstance()->Clear();
537 } 523 }
538 524
539 // Start the process dump. This involves task runner hops as specified by the 525 // Start the process dump. This involves task runner hops as specified by the
540 // MemoryDumpProvider(s) in RegisterDumpProvider()). 526 // MemoryDumpProvider(s) in RegisterDumpProvider()).
541 SetupNextMemoryDump(std::move(pmd_async_state)); 527 SetupNextMemoryDump(std::move(pmd_async_state));
542 } 528 }
543 529
544 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A 530 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A
545 // PostTask is always required for a generic SequencedTaskRunner to ensure that 531 // PostTask is always required for a generic SequencedTaskRunner to ensure that
546 // no other task is running on it concurrently. SetupNextMemoryDump() and 532 // no other task is running on it concurrently. SetupNextMemoryDump() and
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 args); 688 args);
703 bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd); 689 bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd);
704 mdpinfo->consecutive_failures = 690 mdpinfo->consecutive_failures =
705 dump_successful ? 0 : mdpinfo->consecutive_failures + 1; 691 dump_successful ? 0 : mdpinfo->consecutive_failures + 1;
706 } 692 }
707 693
708 pmd_async_state->pending_dump_providers.pop_back(); 694 pmd_async_state->pending_dump_providers.pop_back();
709 SetupNextMemoryDump(std::move(pmd_async_state)); 695 SetupNextMemoryDump(std::move(pmd_async_state));
710 } 696 }
711 697
712 bool MemoryDumpManager::PollFastMemoryTotal(uint64_t* memory_total) {
713 #if DCHECK_IS_ON()
714 {
715 AutoLock lock(lock_);
716 if (dump_thread_)
717 DCHECK(dump_thread_->task_runner()->BelongsToCurrentThread());
718 }
719 #endif
720 if (dump_providers_for_polling_.empty())
721 return false;
722
723 *memory_total = 0;
724 // Note that we call PollFastMemoryTotal() even if the dump provider is
725 // disabled (unregistered). This is to avoid taking lock while polling.
726 for (const auto& mdpinfo : dump_providers_for_polling_) {
727 uint64_t value = 0;
728 mdpinfo->dump_provider->PollFastMemoryTotal(&value);
729 *memory_total += value;
730 }
731 return true;
732 }
733
734 // static 698 // static
735 uint32_t MemoryDumpManager::GetDumpsSumKb(const std::string& pattern, 699 uint32_t MemoryDumpManager::GetDumpsSumKb(const std::string& pattern,
736 const ProcessMemoryDump* pmd) { 700 const ProcessMemoryDump* pmd) {
737 uint64_t sum = 0; 701 uint64_t sum = 0;
738 for (const auto& kv : pmd->allocator_dumps()) { 702 for (const auto& kv : pmd->allocator_dumps()) {
739 auto name = StringPiece(kv.first); 703 auto name = StringPiece(kv.first);
740 if (MatchPattern(name, pattern)) 704 if (MatchPattern(name, pattern))
741 sum += kv.second->GetSize(); 705 sum += kv.second->GetSize();
742 } 706 }
743 return sum / 1024; 707 return sum / 1024;
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( 834 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>(
871 session_state, &MemoryDumpSessionState::stack_frame_deduplicator)); 835 session_state, &MemoryDumpSessionState::stack_frame_deduplicator));
872 836
873 TRACE_EVENT_API_ADD_METADATA_EVENT( 837 TRACE_EVENT_API_ADD_METADATA_EVENT(
874 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", 838 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames",
875 "typeNames", 839 "typeNames",
876 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( 840 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>(
877 session_state, &MemoryDumpSessionState::type_name_deduplicator)); 841 session_state, &MemoryDumpSessionState::type_name_deduplicator));
878 } 842 }
879 843
880 { 844 AutoLock lock(lock_);
881 AutoLock lock(lock_);
882 845
883 DCHECK(delegate_); // At this point we must have a delegate. 846 DCHECK(delegate_); // At this point we must have a delegate.
884 session_state_ = session_state; 847 session_state_ = session_state;
885 848
886 DCHECK(!dump_thread_); 849 DCHECK(!dump_thread_);
887 dump_thread_ = std::move(dump_thread); 850 dump_thread_ = std::move(dump_thread);
888 851
889 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); 852 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
890 853
891 dump_providers_for_polling_.clear(); 854 MemoryDumpScheduler::Config periodic_config = {};
892 for (const auto& mdpinfo : dump_providers_) { 855 MemoryPeakDetector::Config peak_config = {};
893 if (mdpinfo->options.is_fast_polling_supported) 856 for (const auto& trigger : memory_dump_config.triggers) {
894 dump_providers_for_polling_.insert(mdpinfo); 857 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) {
858 NOTREACHED();
859 continue;
895 } 860 }
896 861 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) {
897 MemoryDumpScheduler* dump_scheduler = MemoryDumpScheduler::GetInstance(); 862 periodic_config.triggers.push_back(
898 dump_scheduler->Setup(this, dump_thread_->task_runner()); 863 {trigger.level_of_detail, trigger.min_time_between_dumps_ms});
899 DCHECK_LE(memory_dump_config.triggers.size(), 3u); 864 } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) {
900 for (const auto& trigger : memory_dump_config.triggers) { 865 MemoryPeakDetector::GetInstance()->Setup(
901 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) { 866 Bind(&MemoryDumpManager::GetDumpProvidersForPolling,
902 NOTREACHED(); 867 Unretained(this)),
903 continue; 868 dump_thread_->task_runner(),
904 } 869 Bind(&OnPeakDetected, trigger.level_of_detail));
ssid 2017/04/05 22:04:22 Actually there is no reason to have a Setup() and
Primiano Tucci (use gerrit) 2017/04/10 19:16:41 I want to keep them separate because they will be
905 dump_scheduler->AddTrigger(trigger.trigger_type, trigger.level_of_detail, 870 peak_config.polling_interval_ms = 10;
906 trigger.min_time_between_dumps_ms); 871 peak_config.min_time_between_peaks_ms = trigger.min_time_between_dumps_ms;
872 peak_config.enable_verbose_poll_tracing =
873 trigger.level_of_detail == MemoryDumpLevelOfDetail::DETAILED;
907 } 874 }
908
909 // Notify polling supported only if some polling supported provider was
910 // registered, else RegisterPollingMDPOnDumpThread() will notify when first
911 // polling MDP registers.
912 if (!dump_providers_for_polling_.empty())
913 dump_scheduler->EnablePollingIfNeeded();
914
915 // Only coordinator process triggers periodic global memory dumps.
916 if (delegate_->IsCoordinator())
917 dump_scheduler->EnablePeriodicTriggerIfNeeded();
918 } 875 }
919 876
ssid 2017/04/05 22:04:22 Can we not add support for periodic+peak triggers
Primiano Tucci (use gerrit) 2017/04/10 19:16:41 Is there a specific reason? Nothing should break r
ssid 2017/04/10 21:35:50 yeah should work fine. I will give it a try once t
877 if (peak_config.min_time_between_peaks_ms)
878 MemoryPeakDetector::GetInstance()->Start(peak_config);
ssid 2017/04/05 22:04:22 can move this inot the if above.
Primiano Tucci (use gerrit) 2017/04/10 19:16:41 ?
ssid 2017/04/10 21:35:51 I meant this can be done in the if (trigger.trigge
Primiano Tucci (use gerrit) 2017/04/11 11:43:08 Ahh. Done
879
880 // Only coordinator process triggers periodic global memory dumps.
881 if (delegate_->IsCoordinator() && !periodic_config.triggers.empty()) {
882 MemoryDumpScheduler::GetInstance()->Start(periodic_config,
883 dump_thread_->task_runner());
884 }
920 } 885 }
921 886
922 void MemoryDumpManager::OnTraceLogDisabled() { 887 void MemoryDumpManager::OnTraceLogDisabled() {
923 // There might be a memory dump in progress while this happens. Therefore, 888 // There might be a memory dump in progress while this happens. Therefore,
924 // ensure that the MDM state which depends on the tracing enabled / disabled 889 // ensure that the MDM state which depends on the tracing enabled / disabled
925 // state is always accessed by the dumping methods holding the |lock_|. 890 // state is always accessed by the dumping methods holding the |lock_|.
926 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) 891 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_))
927 return; 892 return;
928 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); 893 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
929 std::unique_ptr<Thread> dump_thread; 894 std::unique_ptr<Thread> dump_thread;
930 { 895 {
931 AutoLock lock(lock_); 896 AutoLock lock(lock_);
897 MemoryDumpScheduler::GetInstance()->Stop();
898 MemoryPeakDetector::GetInstance()->TearDown();
932 dump_thread = std::move(dump_thread_); 899 dump_thread = std::move(dump_thread_);
933 session_state_ = nullptr; 900 session_state_ = nullptr;
934 MemoryDumpScheduler::GetInstance()->DisableAllTriggers();
935 } 901 }
936 902
937 // Thread stops are blocking and must be performed outside of the |lock_| 903 // Thread stops are blocking and must be performed outside of the |lock_|
938 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). 904 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it).
939 if (dump_thread) 905 if (dump_thread)
940 dump_thread->Stop(); 906 dump_thread->Stop();
941
942 // |dump_providers_for_polling_| must be cleared only after the dump thread is
943 // stopped (polling tasks are done).
944 {
945 AutoLock lock(lock_);
946 for (const auto& mdpinfo : dump_providers_for_polling_)
947 mdpinfo->dump_provider->SuspendFastMemoryPolling();
948 dump_providers_for_polling_.clear();
949 }
950 } 907 }
951 908
952 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { 909 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) {
953 AutoLock lock(lock_); 910 AutoLock lock(lock_);
954 if (!session_state_) 911 if (!session_state_)
955 return false; 912 return false;
956 return session_state_->IsDumpModeAllowed(dump_mode); 913 return session_state_->IsDumpModeAllowed(dump_mode);
957 } 914 }
958 915
959 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( 916 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState(
(...skipping 22 matching lines...) Expand all
982 if (iter == process_dumps.end()) { 939 if (iter == process_dumps.end()) {
983 std::unique_ptr<ProcessMemoryDump> new_pmd( 940 std::unique_ptr<ProcessMemoryDump> new_pmd(
984 new ProcessMemoryDump(session_state, dump_args)); 941 new ProcessMemoryDump(session_state, dump_args));
985 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; 942 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first;
986 } 943 }
987 return iter->second.get(); 944 return iter->second.get();
988 } 945 }
989 946
990 } // namespace trace_event 947 } // namespace trace_event
991 } // namespace base 948 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698