Index: services/resource_coordinator/memory/coordinator/coordinator_impl.cc |
diff --git a/services/resource_coordinator/memory/coordinator/coordinator_impl.cc b/services/resource_coordinator/memory/coordinator/coordinator_impl.cc |
deleted file mode 100644 |
index 923d6c1849b9229c96a563e48e258546a7f301c9..0000000000000000000000000000000000000000 |
--- a/services/resource_coordinator/memory/coordinator/coordinator_impl.cc |
+++ /dev/null |
@@ -1,303 +0,0 @@ |
-// Copyright 2017 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "services/resource_coordinator/memory/coordinator/coordinator_impl.h" |
- |
-#include <utility> |
- |
-#include "base/bind.h" |
-#include "base/bind_helpers.h" |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/memory/ref_counted.h" |
-#include "base/threading/thread_task_runner_handle.h" |
-#include "base/trace_event/memory_dump_manager.h" |
-#include "base/trace_event/memory_dump_request_args.h" |
-#include "services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h" |
-#include "services/resource_coordinator/public/interfaces/memory/constants.mojom.h" |
-#include "services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom.h" |
-#include "services/service_manager/public/cpp/identity.h" |
- |
-#if defined(OS_MACOSX) && !defined(OS_IOS) |
-#include "base/mac/mac_util.h" |
-#endif |
- |
-namespace { |
- |
-memory_instrumentation::CoordinatorImpl* g_coordinator_impl; |
- |
-// See design docs linked in the bugs for the rationale of the computation: |
-// - Linux/Android: https://crbug.com/707019 . |
-// - Mac OS: https://crbug.com/707021 . |
-// - Win: https://crbug.com/707022 . |
-uint32_t CalculatePrivateFootprintKb( |
- base::trace_event::MemoryDumpCallbackResult::OSMemDump& os_dump) { |
-#if defined(OS_LINUX) || defined(OS_ANDROID) |
- uint64_t rss_anon_bytes = os_dump.platform_private_footprint.rss_anon_bytes; |
- uint64_t vm_swap_bytes = os_dump.platform_private_footprint.vm_swap_bytes; |
- return (rss_anon_bytes + vm_swap_bytes) / 1024; |
-#elif defined(OS_MACOSX) |
- // TODO(erikchen): This calculation is close, but not fully accurate. It |
- // overcounts by anonymous shared memory. |
- if (base::mac::IsAtLeastOS10_12()) { |
- uint64_t phys_footprint_bytes = |
- os_dump.platform_private_footprint.phys_footprint_bytes; |
- return phys_footprint_bytes / 1024; |
- } else { |
- uint64_t internal_bytes = os_dump.platform_private_footprint.internal_bytes; |
- uint64_t compressed_bytes = |
- os_dump.platform_private_footprint.compressed_bytes; |
- return (internal_bytes + compressed_bytes) / 1024; |
- } |
-#else |
- return 0; |
-#endif |
-} |
- |
-} // namespace |
- |
-namespace memory_instrumentation { |
- |
-// static |
-CoordinatorImpl* CoordinatorImpl::GetInstance() { |
- return g_coordinator_impl; |
-} |
- |
-CoordinatorImpl::CoordinatorImpl(bool initialize_memory_dump_manager, |
- service_manager::Connector* connector) |
- : failed_memory_dump_count_(0), |
- initialize_memory_dump_manager_(initialize_memory_dump_manager) { |
- if (initialize_memory_dump_manager) { |
- // TODO(primiano): the current state where the coordinator also creates a |
- // client (ProcessLocalDumpManagerImpl) is contra-intuitive. BrowserMainLoop |
- // should be doing this. |
- ProcessLocalDumpManagerImpl::CreateInstance( |
- ProcessLocalDumpManagerImpl::Config(this, mojom::ProcessType::BROWSER)); |
- base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id( |
- mojom::kServiceTracingProcessId); |
- } |
- process_map_ = base::MakeUnique<ProcessMap>(connector); |
- DCHECK(!g_coordinator_impl); |
- g_coordinator_impl = this; |
-} |
- |
-CoordinatorImpl::~CoordinatorImpl() { |
- g_coordinator_impl = nullptr; |
-} |
- |
-service_manager::Identity CoordinatorImpl::GetClientIdentityForCurrentRequest() |
- const { |
- return bindings_.dispatch_context(); |
-} |
- |
-void CoordinatorImpl::BindCoordinatorRequest( |
- const service_manager::BindSourceInfo& source_info, |
- mojom::CoordinatorRequest request) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- bindings_.AddBinding(this, std::move(request), source_info.identity); |
-} |
- |
-void CoordinatorImpl::RequestGlobalMemoryDump( |
- const base::trace_event::MemoryDumpRequestArgs& args, |
- const RequestGlobalMemoryDumpCallback& callback) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- bool another_dump_already_in_progress = !queued_memory_dump_requests_.empty(); |
- |
- // If this is a periodic or peak memory dump request and there already is |
- // another request in the queue with the same level of detail, there's no |
- // point in enqueuing this request. |
- if (another_dump_already_in_progress && |
- args.dump_type != |
- base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED && |
- args.dump_type != base::trace_event::MemoryDumpType::SUMMARY_ONLY) { |
- for (const auto& request : queued_memory_dump_requests_) { |
- if (request.args.level_of_detail == args.level_of_detail) { |
- VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " (" |
- << base::trace_event::MemoryDumpTypeToString(args.dump_type) |
- << ") skipped because another dump request with the same " |
- "level of detail (" |
- << base::trace_event::MemoryDumpLevelOfDetailToString( |
- args.level_of_detail) |
- << ") is already in the queue"; |
- callback.Run(args.dump_guid, false /* success */, |
- nullptr /* global_memory_dump */); |
- return; |
- } |
- } |
- } |
- |
- queued_memory_dump_requests_.emplace_back(args, callback); |
- |
- // If another dump is already in progress, this dump will automatically be |
- // scheduled when the other dump finishes. |
- if (another_dump_already_in_progress) |
- return; |
- |
- PerformNextQueuedGlobalMemoryDump(); |
-} |
- |
-void CoordinatorImpl::RegisterProcessLocalDumpManager( |
- mojom::ProcessLocalDumpManagerPtr process_manager) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- process_manager.set_connection_error_handler( |
- base::Bind(&CoordinatorImpl::UnregisterProcessLocalDumpManager, |
- base::Unretained(this), process_manager.get())); |
- mojom::ProcessLocalDumpManager* key = process_manager.get(); |
- auto client_info = base::MakeUnique<ClientInfo>( |
- GetClientIdentityForCurrentRequest(), std::move(process_manager)); |
- auto iterator_and_inserted = clients_.emplace(key, std::move(client_info)); |
- DCHECK(iterator_and_inserted.second); |
-} |
- |
-void CoordinatorImpl::UnregisterProcessLocalDumpManager( |
- mojom::ProcessLocalDumpManager* process_manager) { |
- // Check if we are waiting for an ack from this process-local manager. |
- if (pending_clients_for_current_dump_.count(process_manager)) { |
- DCHECK(!queued_memory_dump_requests_.empty()); |
- OnProcessMemoryDumpResponse( |
- process_manager, queued_memory_dump_requests_.front().args.dump_guid, |
- false /* success */, nullptr /* process_memory_dump */); |
- } |
- size_t num_deleted = clients_.erase(process_manager); |
- DCHECK(num_deleted == 1); |
-} |
- |
-void CoordinatorImpl::PerformNextQueuedGlobalMemoryDump() { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!queued_memory_dump_requests_.empty()); |
- const base::trace_event::MemoryDumpRequestArgs& args = |
- queued_memory_dump_requests_.front().args; |
- |
- // No need to treat the service process different than other processes. The |
- // service process will register itself as a ProcessLocalDumpManager and |
- // will be treated like other process-local managers. |
- pending_clients_for_current_dump_.clear(); |
- failed_memory_dump_count_ = 0; |
- for (const auto& kv : clients_) { |
- const mojom::ProcessLocalDumpManagerPtr& client = kv.second->client; |
- pending_clients_for_current_dump_.insert(client.get()); |
- auto callback = base::Bind(&CoordinatorImpl::OnProcessMemoryDumpResponse, |
- base::Unretained(this), client.get()); |
- client->RequestProcessMemoryDump(args, callback); |
- } |
- // Run the callback in case there are no process-local managers. |
- FinalizeGlobalMemoryDumpIfAllManagersReplied(); |
-} |
- |
-void CoordinatorImpl::OnProcessMemoryDumpResponse( |
- mojom::ProcessLocalDumpManager* process_manager, |
- uint64_t dump_guid, |
- bool success, |
- mojom::ProcessMemoryDumpPtr process_memory_dump) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- auto it = pending_clients_for_current_dump_.find(process_manager); |
- |
- if (queued_memory_dump_requests_.empty() || |
- queued_memory_dump_requests_.front().args.dump_guid != dump_guid || |
- it == pending_clients_for_current_dump_.end()) { |
- VLOG(1) << "Received unexpected memory dump response: " << dump_guid; |
- return; |
- } |
- if (process_memory_dump) { |
- base::ProcessId pid = base::kNullProcessId; |
- auto it = clients_.find(process_manager); |
- if (it != clients_.end()) { |
- pid = process_map_->GetProcessId(it->second->identity); |
- } |
- |
- queued_memory_dump_requests_.front().process_memory_dumps.push_back( |
- std::make_pair(pid, std::move(process_memory_dump))); |
- } |
- |
- pending_clients_for_current_dump_.erase(it); |
- |
- if (!success) { |
- ++failed_memory_dump_count_; |
- VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix |
- << " failed because of NACK from client"; |
- } |
- |
- FinalizeGlobalMemoryDumpIfAllManagersReplied(); |
-} |
- |
-void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { |
- if (pending_clients_for_current_dump_.size() > 0) |
- return; |
- |
- DCHECK(!queued_memory_dump_requests_.empty()); |
- QueuedMemoryDumpRequest& request = queued_memory_dump_requests_.front(); |
- |
- // Reconstruct a map of pid -> ProcessMemoryDump by reassembling the responses |
- // received by the clients for this dump. In some cases the response coming |
- // from one client can also provide the dump of OS counters for other |
- // processes. A concrete case is Linux, where the browser process provides |
- // details for the child processes to get around sandbox restrictions on |
- // opening /proc pseudo files. |
- std::map<base::ProcessId, mojom::ProcessMemoryDumpPtr> finalized_pmds; |
- for (auto& result : request.process_memory_dumps) { |
- mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[result.first]; |
- if (!pmd) |
- pmd = mojom::ProcessMemoryDump::New(); |
- pmd->chrome_dump = result.second->chrome_dump; |
- |
- // TODO(hjd): We should have a better way to tell if os_dump is filled. |
- if (result.second->os_dump.resident_set_kb > 0) { |
- DCHECK_EQ(0u, pmd->os_dump.resident_set_kb); |
- pmd->os_dump = result.second->os_dump; |
- } |
- |
- for (auto& pair : result.second->extra_processes_dump) { |
- base::ProcessId pid = pair.first; |
- mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[pid]; |
- if (!pmd) |
- pmd = mojom::ProcessMemoryDump::New(); |
- DCHECK_EQ(0u, pmd->os_dump.resident_set_kb); |
- pmd->os_dump = result.second->extra_processes_dump[pid]; |
- } |
- |
- pmd->process_type = result.second->process_type; |
- } |
- |
- mojom::GlobalMemoryDumpPtr global_dump(mojom::GlobalMemoryDump::New()); |
- for (auto& pair : finalized_pmds) { |
- // It's possible that the renderer has died but we still have an os_dump, |
- // because those were computed from the browser proces before the renderer |
- // died. We should skip these. |
- // TODO(hjd): We should have a better way to tell if a chrome_dump is |
- // filled. |
- mojom::ProcessMemoryDumpPtr& pmd = pair.second; |
- if (!pmd || !pmd->chrome_dump.malloc_total_kb) |
- continue; |
- pmd->private_footprint = CalculatePrivateFootprintKb(pmd->os_dump); |
- global_dump->process_dumps.push_back(std::move(pmd)); |
- } |
- |
- const auto& callback = request.callback; |
- const bool global_success = failed_memory_dump_count_ == 0; |
- callback.Run(request.args.dump_guid, global_success, std::move(global_dump)); |
- queued_memory_dump_requests_.pop_front(); |
- |
- // Schedule the next queued dump (if applicable). |
- if (!queued_memory_dump_requests_.empty()) { |
- base::ThreadTaskRunnerHandle::Get()->PostTask( |
- FROM_HERE, |
- base::Bind(&CoordinatorImpl::PerformNextQueuedGlobalMemoryDump, |
- base::Unretained(this))); |
- } |
-} |
- |
-CoordinatorImpl::QueuedMemoryDumpRequest::QueuedMemoryDumpRequest( |
- const base::trace_event::MemoryDumpRequestArgs& args, |
- const RequestGlobalMemoryDumpCallback callback) |
- : args(args), callback(callback) {} |
- |
-CoordinatorImpl::QueuedMemoryDumpRequest::~QueuedMemoryDumpRequest() {} |
- |
-CoordinatorImpl::ClientInfo::ClientInfo( |
- const service_manager::Identity& identity, |
- mojom::ProcessLocalDumpManagerPtr client) |
- : identity(identity), client(std::move(client)) {} |
-CoordinatorImpl::ClientInfo::~ClientInfo() {} |
- |
-} // namespace memory_instrumentation |