blob: 09b32283892bbd0e124f471936e33ae82eabb750 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/services/heap_profiling/heap_profiling_service.h"
#include <memory>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/task/thread_pool.h"
#include "components/services/heap_profiling/connection_manager.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
namespace heap_profiling {
namespace {
class ProfilingServiceImpl;
class ProfilingServiceImpl
: public mojom::ProfilingService,
public memory_instrumentation::mojom::HeapProfiler {
public:
ProfilingServiceImpl(
mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
profiler_receiver,
mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
helper)
: heap_profiler_receiver_(this, std::move(profiler_receiver)),
helper_(std::move(helper)) {}
ProfilingServiceImpl(const ProfilingServiceImpl&) = delete;
ProfilingServiceImpl& operator=(const ProfilingServiceImpl&) = delete;
~ProfilingServiceImpl() override = default;
// mojom::ProfilingService implementation:
void AddProfilingClient(
base::ProcessId pid,
mojo::PendingRemote<mojom::ProfilingClient> client,
mojom::ProcessType process_type,
mojom::ProfilingParamsPtr params,
base::OnceClosure started_profiling_closure) override {
if (params->sampling_rate == 0)
params->sampling_rate = 1;
connection_manager_.OnNewConnection(pid, std::move(client), process_type,
std::move(params),
std::move(started_profiling_closure));
}
void GetProfiledPids(GetProfiledPidsCallback callback) override {
std::move(callback).Run(connection_manager_.GetConnectionPids());
}
// memory_instrumentation::mojom::HeapProfiler implementation:
void DumpProcessesForTracing(
bool strip_path_from_mapped_files,
bool write_proto,
DumpProcessesForTracingCallback callback) override {
std::vector<base::ProcessId> pids =
connection_manager_.GetConnectionPidsThatNeedVmRegions();
if (pids.empty()) {
connection_manager_.DumpProcessesForTracing(
strip_path_from_mapped_files, write_proto, std::move(callback),
VmRegions());
return;
}
// Need a memory map to make sense of the dump. The dump will be triggered
// in the memory map global dump callback.
helper_->GetVmRegionsForHeapProfiler(
pids,
base::BindOnce(&ProfilingServiceImpl::
OnGetVmRegionsCompleteForDumpProcessesForTracing,
weak_factory_.GetWeakPtr(), strip_path_from_mapped_files,
write_proto, std::move(callback)));
}
private:
void OnGetVmRegionsCompleteForDumpProcessesForTracing(
bool strip_path_from_mapped_files,
bool write_proto,
DumpProcessesForTracingCallback callback,
VmRegions vm_regions) {
connection_manager_.DumpProcessesForTracing(
strip_path_from_mapped_files, write_proto, std::move(callback),
std::move(vm_regions));
}
mojo::Receiver<memory_instrumentation::mojom::HeapProfiler>
heap_profiler_receiver_{this};
mojo::Remote<memory_instrumentation::mojom::HeapProfilerHelper> helper_;
ConnectionManager connection_manager_;
base::WeakPtrFactory<ProfilingServiceImpl> weak_factory_{this};
};
void RunHeapProfilingService(
mojo::PendingReceiver<mojom::ProfilingService> receiver,
mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
profiler_receiver,
mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
helper) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<ProfilingServiceImpl>(std::move(profiler_receiver),
std::move(helper)),
std::move(receiver));
}
} // namespace
mojo::PendingRemote<mojom::ProfilingService> LaunchService(
mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
profiler_receiver,
mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
helper) {
mojo::PendingRemote<mojom::ProfilingService> remote;
auto task_runner = base::ThreadPool::CreateSingleThreadTaskRunner(
{base::TaskPriority::BEST_EFFORT, base::WithBaseSyncPrimitives()},
base::SingleThreadTaskRunnerThreadMode::DEDICATED);
task_runner->PostTask(
FROM_HERE,
base::BindOnce(&RunHeapProfilingService,
remote.InitWithNewPipeAndPassReceiver(),
std::move(profiler_receiver), std::move(helper)));
return remote;
}
} // namespace heap_profiling