OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |