Chromium Code Reviews| Index: base/trace_event/memory_dump_manager.cc |
| diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc |
| index 096eaf88487828c43ca9748182282eeed73df80a..d54352cb08b535a2aeacbdcb8bd3eabbedade343 100644 |
| --- a/base/trace_event/memory_dump_manager.cc |
| +++ b/base/trace_event/memory_dump_manager.cc |
| @@ -25,6 +25,7 @@ |
| #include "base/trace_event/malloc_dump_provider.h" |
| #include "base/trace_event/memory_dump_provider.h" |
| #include "base/trace_event/memory_dump_session_state.h" |
| +#include "base/trace_event/memory_dump_trigger.h" |
| #include "base/trace_event/memory_infra_background_whitelist.h" |
| #include "base/trace_event/process_memory_dump.h" |
| #include "base/trace_event/trace_event.h" |
| @@ -128,7 +129,6 @@ void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { |
| MemoryDumpManager::MemoryDumpManager() |
| : delegate_(nullptr), |
| - is_coordinator_(false), |
| memory_tracing_enabled_(0), |
| tracing_process_id_(kInvalidTracingProcessId), |
| dumper_registrations_ignored_for_testing_(false), |
| @@ -188,8 +188,8 @@ void MemoryDumpManager::Initialize(MemoryDumpManagerDelegate* delegate, |
| DCHECK(delegate); |
| DCHECK(!delegate_); |
| delegate_ = delegate; |
| - is_coordinator_ = is_coordinator; |
| EnableHeapProfilingIfNeeded(); |
| + dump_trigger_.reset(new MemoryDumpTrigger(this, is_coordinator)); |
| } |
| // Enable the core dump providers. |
| @@ -374,6 +374,15 @@ void MemoryDumpManager::RegisterPollingMDPOnDumpThread( |
| DCHECK(!mdpinfo->task_runner); |
| AutoLock lock(lock_); |
| dump_providers_for_polling_.insert(mdpinfo); |
| + |
| + // Setup polling when first polling supported provider is registered since |
| + // OnTraceLogEnabled() would not have setup polling without any provider that |
| + // supports polling. |
|
Primiano Tucci (use gerrit)
2017/01/18 16:16:06
can you expand a bit here about why? To me feels a
ssid
2017/01/20 23:07:27
If I did that then we would be unnecessarily setti
|
| + if (dump_providers_for_polling_.size() == 1) { |
| + dump_trigger_->SetupPeakTriggers( |
| + session_state_->memory_dump_config().triggers, |
| + ThreadTaskRunnerHandle::Get()); |
|
Primiano Tucci (use gerrit)
2017/01/18 16:16:06
this one confuses me a bit: how do you know at thi
ssid
2017/01/20 23:07:27
So, now it does not matter. The scheduler knows if
|
| + } |
| } |
| void MemoryDumpManager::UnregisterPollingMDPOnDumpThread( |
| @@ -382,6 +391,9 @@ void MemoryDumpManager::UnregisterPollingMDPOnDumpThread( |
| AutoLock lock(lock_); |
| dump_providers_for_polling_.erase(mdpinfo); |
| + DCHECK(!dump_providers_for_polling_.empty()) |
| + << "All polling MDPs cannot be unregistered, since it will cause polling " |
| + "without without any MDPs"; |
| } |
| void MemoryDumpManager::RequestGlobalDump( |
| @@ -637,7 +649,17 @@ void MemoryDumpManager::InvokeOnMemoryDump( |
| SetupNextMemoryDump(std::move(pmd_async_state)); |
| } |
| -void MemoryDumpManager::PollFastMemoryTotal(uint64_t* memory_total) { |
| +bool MemoryDumpManager::PollFastMemoryTotal(uint64_t* memory_total) { |
| +#if DCHECK_IS_ON() |
| + { |
| + AutoLock lock(lock_); |
| + if (dump_thread_) |
| + DCHECK(dump_thread_->task_runner()->BelongsToCurrentThread()); |
| + } |
| +#endif |
| + if (dump_providers_for_polling_.empty()) |
| + return false; |
| + |
| *memory_total = 0; |
| // Note that we call PollFastMemoryTotal() even if the dump provider is |
| // disabled (unregistered). This is to avoid taking lock while polling. |
| @@ -646,7 +668,7 @@ void MemoryDumpManager::PollFastMemoryTotal(uint64_t* memory_total) { |
| mdpinfo->dump_provider->PollFastMemoryTotal(&value); |
| *memory_total += value; |
| } |
| - return; |
| + return true; |
| } |
| // static |
| @@ -753,6 +775,8 @@ void MemoryDumpManager::OnTraceLogEnabled() { |
| session_state, &MemoryDumpSessionState::type_name_deduplicator)); |
| } |
| + scoped_refptr<SingleThreadTaskRunner> polling_task_runner; |
| + MemoryDumpTrigger* trigger = nullptr; |
| { |
| AutoLock lock(lock_); |
| @@ -767,21 +791,23 @@ void MemoryDumpManager::OnTraceLogEnabled() { |
| if (mdpinfo->options.is_fast_polling_supported) |
| dump_providers_for_polling_.insert(mdpinfo); |
| } |
| + if (!dump_providers_for_polling_.empty()) |
| + polling_task_runner = dump_thread_->task_runner(); |
| subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
| - // TODO(primiano): This is a temporary hack to disable periodic memory dumps |
| - // when running memory benchmarks until telemetry uses TraceConfig to |
| - // enable/disable periodic dumps. See crbug.com/529184 . |
| - if (!is_coordinator_ || |
| - CommandLine::ForCurrentProcess()->HasSwitch( |
| - "enable-memory-benchmarking")) { |
| - return; |
| - } |
| + trigger = dump_trigger_.get(); |
| } |
| + // Setup peak triggers only if some polling supported provider was registered, |
| + // else polling will be setup by RegisterPollingMDPOnDumpThread when first |
| + // polling MDP registers. |
| + if (polling_task_runner) { |
| + trigger->SetupPeakTriggers(trace_config.memory_dump_config().triggers, |
| + polling_task_runner); |
| + } |
| // Enable periodic dumps if necessary. |
| - periodic_dump_timer_.Start(trace_config.memory_dump_config().triggers); |
| + trigger->SetupPeriodicTriggers(trace_config.memory_dump_config().triggers); |
| } |
| void MemoryDumpManager::OnTraceLogDisabled() { |
| @@ -800,18 +826,20 @@ void MemoryDumpManager::OnTraceLogDisabled() { |
| // Thread stops are blocking and must be performed outside of the |lock_| |
| // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). |
| - periodic_dump_timer_.Stop(); |
| if (dump_thread) |
| dump_thread->Stop(); |
| - // |dump_providers_for_polling_| must be cleared only after the dump thread is |
| - // stopped (polling tasks are done). |
| + // |dump_providers_for_polling_| must be cleared and triggers must be |
| + // disabled only after the dump thread is stopped (polling tasks are done). |
| + MemoryDumpTrigger* trigger = nullptr; |
| { |
| AutoLock lock(lock_); |
| for (const auto& mdpinfo : dump_providers_for_polling_) |
| mdpinfo->dump_provider->SuspendFastMemoryPolling(); |
| dump_providers_for_polling_.clear(); |
| + trigger = dump_trigger_.get(); |
| } |
| + trigger->Disable(); |
| } |
| bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { |
| @@ -885,80 +913,5 @@ ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: |
| return iter->second.get(); |
| } |
| -MemoryDumpManager::PeriodicGlobalDumpTimer::PeriodicGlobalDumpTimer() {} |
| - |
| -MemoryDumpManager::PeriodicGlobalDumpTimer::~PeriodicGlobalDumpTimer() { |
| - Stop(); |
| -} |
| - |
| -void MemoryDumpManager::PeriodicGlobalDumpTimer::Start( |
| - const std::vector<TraceConfig::MemoryDumpConfig::Trigger>& triggers_list) { |
| - if (triggers_list.empty()) |
| - return; |
| - |
| - // At the moment the periodic support is limited to at most one periodic |
| - // trigger per dump mode. All intervals should be an integer multiple of the |
| - // smallest interval specified. |
| - periodic_dumps_count_ = 0; |
| - uint32_t min_timer_period_ms = std::numeric_limits<uint32_t>::max(); |
| - uint32_t light_dump_period_ms = 0; |
| - uint32_t heavy_dump_period_ms = 0; |
| - DCHECK_LE(triggers_list.size(), 3u); |
| - auto* mdm = MemoryDumpManager::GetInstance(); |
| - for (const TraceConfig::MemoryDumpConfig::Trigger& config : triggers_list) { |
| - DCHECK_NE(0u, config.min_time_between_dumps_ms); |
| - DCHECK_EQ(MemoryDumpType::PERIODIC_INTERVAL, config.trigger_type) |
| - << "Only periodic_interval triggers are suppported"; |
| - switch (config.level_of_detail) { |
| - case MemoryDumpLevelOfDetail::BACKGROUND: |
| - DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::BACKGROUND)); |
| - break; |
| - case MemoryDumpLevelOfDetail::LIGHT: |
| - DCHECK_EQ(0u, light_dump_period_ms); |
| - DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::LIGHT)); |
| - light_dump_period_ms = config.min_time_between_dumps_ms; |
| - break; |
| - case MemoryDumpLevelOfDetail::DETAILED: |
| - DCHECK_EQ(0u, heavy_dump_period_ms); |
| - DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::DETAILED)); |
| - heavy_dump_period_ms = config.min_time_between_dumps_ms; |
| - break; |
| - } |
| - min_timer_period_ms = |
| - std::min(min_timer_period_ms, config.min_time_between_dumps_ms); |
| - } |
| - |
| - DCHECK_EQ(0u, light_dump_period_ms % min_timer_period_ms); |
| - light_dump_rate_ = light_dump_period_ms / min_timer_period_ms; |
| - DCHECK_EQ(0u, heavy_dump_period_ms % min_timer_period_ms); |
| - heavy_dump_rate_ = heavy_dump_period_ms / min_timer_period_ms; |
| - |
| - timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(min_timer_period_ms), |
| - base::Bind(&PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump, |
| - base::Unretained(this))); |
| -} |
| - |
| -void MemoryDumpManager::PeriodicGlobalDumpTimer::Stop() { |
| - if (IsRunning()) { |
| - timer_.Stop(); |
| - } |
| -} |
| - |
| -bool MemoryDumpManager::PeriodicGlobalDumpTimer::IsRunning() { |
| - return timer_.IsRunning(); |
| -} |
| - |
| -void MemoryDumpManager::PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump() { |
| - MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; |
| - if (light_dump_rate_ > 0 && periodic_dumps_count_ % light_dump_rate_ == 0) |
| - level_of_detail = MemoryDumpLevelOfDetail::LIGHT; |
| - if (heavy_dump_rate_ > 0 && periodic_dumps_count_ % heavy_dump_rate_ == 0) |
| - level_of_detail = MemoryDumpLevelOfDetail::DETAILED; |
| - ++periodic_dumps_count_; |
| - |
| - MemoryDumpManager::GetInstance()->RequestGlobalDump( |
| - MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
| -} |
| - |
| } // namespace trace_event |
| } // namespace base |