Commit ec6a7a25 authored by Erik Chen's avatar Erik Chen Committed by Commit Bot

Speed up module dumps on macOS.

The out of process heap profiler only requires modules to be dumped, not every
single virtual memory region. This CL modifies the interface to support this,
and updates the macOS implementation to be much faster. The other OSes currently
still perform full address space dumps - this can be changed in the future if it
proves to be a performance issue.

Bug: 826913
Change-Id: Ibaa03d3dfae71a2b6d090aed0ab2ffdc4bb090a9
Reviewed-on: https://chromium-review.googlesource.com/986680
Commit-Queue: Erik Chen <erikchen@chromium.org>
Reviewed-by: default avatarPrimiano Tucci <primiano@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548731}
parent a992c363
......@@ -45,8 +45,6 @@ const char* MemoryDumpLevelOfDetailToString(
return "background";
case MemoryDumpLevelOfDetail::LIGHT:
return "light";
case MemoryDumpLevelOfDetail::VM_REGIONS_ONLY_FOR_HEAP_PROFILER:
return "vm_regions_only";
case MemoryDumpLevelOfDetail::DETAILED:
return "detailed";
}
......@@ -60,8 +58,6 @@ MemoryDumpLevelOfDetail StringToMemoryDumpLevelOfDetail(
return MemoryDumpLevelOfDetail::BACKGROUND;
if (str == "light")
return MemoryDumpLevelOfDetail::LIGHT;
if (str == "vm_regions_only")
return MemoryDumpLevelOfDetail::VM_REGIONS_ONLY_FOR_HEAP_PROFILER;
if (str == "detailed")
return MemoryDumpLevelOfDetail::DETAILED;
NOTREACHED();
......
......@@ -53,9 +53,6 @@ enum class MemoryDumpLevelOfDetail : uint32_t {
// Few entries, typically a fixed number, per dump.
LIGHT,
// Retrieve only memory maps. Used only for the heap profiler.
VM_REGIONS_ONLY_FOR_HEAP_PROFILER,
// Unrestricted amount of entries per dump.
DETAILED,
......
......@@ -50,11 +50,6 @@ void MemoryDumpScheduler::StartInternal(MemoryDumpScheduler::Config config) {
for (const Config::Trigger& trigger : config.triggers) {
DCHECK_GT(trigger.period_ms, 0u);
switch (trigger.level_of_detail) {
case MemoryDumpLevelOfDetail::VM_REGIONS_ONLY_FOR_HEAP_PROFILER:
// There is no use case to request a periodic dump which contains
// details that are useful only for the heap-profiler.
NOTREACHED();
return;
case MemoryDumpLevelOfDetail::BACKGROUND:
break;
case MemoryDumpLevelOfDetail::LIGHT:
......
......@@ -168,7 +168,7 @@ class MockClientProcess : public mojom::ClientProcess {
}));
ON_CALL(*this, RequestOSMemoryDump(_, _, _))
.WillByDefault(Invoke([](bool want_mmaps,
.WillByDefault(Invoke([](mojom::MemoryMapOption,
const std::vector<base::ProcessId> pids,
const RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
......@@ -183,7 +183,7 @@ class MockClientProcess : public mojom::ClientProcess {
const RequestChromeMemoryDumpCallback& callback));
MOCK_METHOD3(RequestOSMemoryDump,
void(bool want_mmaps,
void(mojom::MemoryMapOption option,
const std::vector<base::ProcessId>& args,
const RequestOSMemoryDumpCallback& callback));
......@@ -324,7 +324,7 @@ TEST_F(CoordinatorImplTest, MissingOsDump) {
EXPECT_CALL(client_process, RequestOSMemoryDump(_, _, _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
callback.Run(true, std::move(results));
......@@ -391,7 +391,7 @@ TEST_F(CoordinatorImplTest, TimeOutStuckChildMultiProcess) {
RequestOSMemoryDump(
_, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[kBrowserPid] = FillRawOSDump(kBrowserPid);
......@@ -402,7 +402,7 @@ TEST_F(CoordinatorImplTest, TimeOutStuckChildMultiProcess) {
#else
EXPECT_CALL(browser_client, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = FillRawOSDump(kBrowserPid);
......@@ -410,7 +410,7 @@ TEST_F(CoordinatorImplTest, TimeOutStuckChildMultiProcess) {
}));
EXPECT_CALL(renderer_client, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = FillRawOSDump(kRendererPid);
......@@ -570,7 +570,7 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
EXPECT_CALL(browser_client,
RequestOSMemoryDump(_, AllOf(Contains(1), Contains(2)), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[1] = mojom::RawOSMemDump::New();
......@@ -587,7 +587,7 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
#else
EXPECT_CALL(browser_client, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = mojom::RawOSMemDump::New();
......@@ -598,7 +598,7 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
}));
EXPECT_CALL(renderer_client, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = mojom::RawOSMemDump::New();
......@@ -652,12 +652,11 @@ TEST_F(CoordinatorImplTest, VmRegionsForHeapProfiler) {
// On Linux, all memory dumps come from the browser client. On all other
// platforms, they are expected to come from each individual client.
#if defined(OS_LINUX)
EXPECT_CALL(
browser_client,
EXPECT_CALL(browser_client,
RequestOSMemoryDump(
true, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
_, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[kBrowserPid] = FillRawOSDump(kBrowserPid);
......@@ -668,7 +667,7 @@ TEST_F(CoordinatorImplTest, VmRegionsForHeapProfiler) {
#else
EXPECT_CALL(browser_client, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = FillRawOSDump(kBrowserPid);
......@@ -676,7 +675,7 @@ TEST_F(CoordinatorImplTest, VmRegionsForHeapProfiler) {
}));
EXPECT_CALL(renderer_client, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = FillRawOSDump(kRendererPid);
......@@ -819,21 +818,21 @@ TEST_F(CoordinatorImplTest, DumpByPidSuccess) {
#if defined(OS_LINUX)
EXPECT_CALL(client_process_1, RequestOSMemoryDump(_, _, _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[kBrowserPid] = FillRawOSDump(kBrowserPid);
callback.Run(true, std::move(results));
}))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[kRendererPid] = FillRawOSDump(kRendererPid);
callback.Run(true, std::move(results));
}))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[kGpuPid] = FillRawOSDump(kGpuPid);
......@@ -842,7 +841,7 @@ TEST_F(CoordinatorImplTest, DumpByPidSuccess) {
#else
EXPECT_CALL(client_process_1, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = FillRawOSDump(kBrowserPid);
......@@ -850,7 +849,7 @@ TEST_F(CoordinatorImplTest, DumpByPidSuccess) {
}));
EXPECT_CALL(client_process_2, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = FillRawOSDump(kRendererPid);
......@@ -858,7 +857,7 @@ TEST_F(CoordinatorImplTest, DumpByPidSuccess) {
}));
EXPECT_CALL(client_process_3, RequestOSMemoryDump(_, Contains(0), _))
.WillOnce(Invoke(
[](bool want_mmaps, const std::vector<base::ProcessId>& pids,
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
const MockClientProcess::RequestOSMemoryDumpCallback& callback) {
std::unordered_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
results[0] = FillRawOSDump(kGpuPid);
......
......@@ -74,18 +74,11 @@ struct QueuedRequest {
base::trace_event::MemoryDumpRequestArgs GetRequestArgs();
bool wants_mmaps() const {
return args.level_of_detail == base::trace_event::MemoryDumpLevelOfDetail::
VM_REGIONS_ONLY_FOR_HEAP_PROFILER ||
args.level_of_detail ==
base::trace_event::MemoryDumpLevelOfDetail::DETAILED;
}
// We always want to return chrome dumps, with exception of the special
// case below for the heap profiler, which cares only about mmaps.
bool wants_chrome_dumps() const {
return args.level_of_detail != base::trace_event::MemoryDumpLevelOfDetail::
VM_REGIONS_ONLY_FOR_HEAP_PROFILER;
mojom::MemoryMapOption memory_map_option() const {
return args.level_of_detail ==
base::trace_event::MemoryDumpLevelOfDetail::DETAILED
? mojom::MemoryMapOption::FULL
: mojom::MemoryMapOption::NONE;
}
bool should_return_summaries() const {
......
......@@ -187,10 +187,6 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
DCHECK(!request->dump_in_progress);
request->dump_in_progress = true;
// A request must be either !VM_REGIONS_ONLY or, in the special case of the
// heap profiler, must be of DETAILED type.
DCHECK(request->wants_chrome_dumps() || request->wants_mmaps());
request->start_time = base::Time::Now();
TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
......@@ -228,17 +224,16 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
// OSMemoryDump until the Chrome memory dump is finished. See
// https://bugs.chromium.org/p/chromium/issues/detail?id=812346#c16 for more
// details.
if (request->wants_chrome_dumps()) {
request->pending_responses.insert({client, ResponseType::kChromeDump});
client->RequestChromeMemoryDump(request->GetRequestArgs(),
base::Bind(chrome_callback, client));
}
// On most platforms each process can dump data about their own process
// so ask each process to do so Linux is special see below.
#if !defined(OS_LINUX)
request->pending_responses.insert({client, ResponseType::kOSDump});
client->RequestOSMemoryDump(request->wants_mmaps(), {base::kNullProcessId},
client->RequestOSMemoryDump(request->memory_map_option(),
{base::kNullProcessId},
base::Bind(os_callback, client));
#endif // !defined(OS_LINUX)
......@@ -269,7 +264,8 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
if (browser_client && pids.size() > 0) {
request->pending_responses.insert({browser_client, ResponseType::kOSDump});
const auto callback = base::Bind(os_callback, browser_client);
browser_client->RequestOSMemoryDump(request->wants_mmaps(), pids, callback);
browser_client->RequestOSMemoryDump(request->memory_map_option(), pids,
callback);
}
#endif // defined(OS_LINUX)
......@@ -309,8 +305,8 @@ void QueuedRequestDispatcher::SetUpAndDispatchVmRegionRequest(
request->pending_responses.insert(browser_client);
request->responses[browser_client].process_id = browser_client_pid;
const auto callback = base::Bind(os_callback, browser_client);
browser_client->RequestOSMemoryDump(true /* wants_mmaps */, desired_pids,
callback);
browser_client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
desired_pids, callback);
#else
for (const auto& client_info : clients) {
if (std::find(desired_pids.begin(), desired_pids.end(), client_info.pid) !=
......@@ -318,7 +314,7 @@ void QueuedRequestDispatcher::SetUpAndDispatchVmRegionRequest(
mojom::ClientProcess* client = client_info.client;
request->pending_responses.insert(client);
request->responses[client].process_id = client_info.pid;
client->RequestOSMemoryDump(true /* wants_mmaps */,
client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
{base::kNullProcessId},
base::Bind(os_callback, client));
}
......@@ -500,9 +496,9 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
}
// Ignore incomplete results (can happen if the client crashes/disconnects).
const bool valid = raw_os_dump &&
(!request->wants_chrome_dumps() || raw_chrome_dump) &&
(!request->wants_mmaps() ||
const bool valid =
raw_os_dump && raw_chrome_dump &&
(request->memory_map_option() == mojom::MemoryMapOption::NONE ||
(raw_os_dump && !raw_os_dump->memory_maps.empty()));
if (!valid)
......
......@@ -136,11 +136,11 @@ void ClientProcessImpl::EnableHeapProfiling(
}
void ClientProcessImpl::RequestOSMemoryDump(
bool want_mmaps,
mojom::MemoryMapOption mmap_option,
const std::vector<base::ProcessId>& pids,
const RequestOSMemoryDumpCallback& callback) {
OSMemoryDumpArgs args;
args.want_mmaps = want_mmaps;
args.mmap_option = mmap_option;
args.pids = pids;
args.callback = callback;
......@@ -166,8 +166,10 @@ void ClientProcessImpl::PerformOSMemoryDump(OSMemoryDumpArgs args) {
mojom::RawOSMemDumpPtr result = mojom::RawOSMemDump::New();
result->platform_private_footprint = mojom::PlatformPrivateFootprint::New();
bool success = OSMetrics::FillOSMemoryDump(pid, result.get());
if (args.want_mmaps)
success = success && OSMetrics::FillProcessMemoryMaps(pid, result.get());
if (args.mmap_option != mojom::MemoryMapOption::NONE) {
success = success && OSMetrics::FillProcessMemoryMaps(
pid, args.mmap_option, result.get());
}
if (success)
results[pid] = std::move(result);
global_success = global_success && success;
......
......@@ -79,7 +79,7 @@ class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT ClientProcessImpl
// mojom::ClientProcess implementation. The Coordinator calls this.
void RequestOSMemoryDump(
bool wants_mmaps,
mojom::MemoryMapOption mmap_option,
const std::vector<base::ProcessId>& ids,
const RequestOSMemoryDumpCallback& callback) override;
......@@ -87,7 +87,7 @@ class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT ClientProcessImpl
OSMemoryDumpArgs();
OSMemoryDumpArgs(const OSMemoryDumpArgs&);
~OSMemoryDumpArgs();
bool want_mmaps = false;
mojom::MemoryMapOption mmap_option;
std::vector<base::ProcessId> pids;
RequestOSMemoryDumpCallback callback;
};
......
......@@ -4,16 +4,32 @@
#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h"
#include "build/build_config.h"
namespace memory_instrumentation {
// static
bool OSMetrics::FillProcessMemoryMaps(base::ProcessId pid,
mojom::MemoryMapOption mmap_option,
mojom::RawOSMemDump* dump) {
auto maps = GetProcessMemoryMaps(pid);
if (maps.empty())
DCHECK_NE(mmap_option, mojom::MemoryMapOption::NONE);
std::vector<mojom::VmRegionPtr> results;
#if defined(OS_MACOSX)
// TODO: Consider implementing this optimization for other platforms as well,
// if performance becomes an issue. https://crbug.com/826913.
if (mmap_option == mojom::MemoryMapOption::MODULES)
results = GetProcessModules(pid);
#endif
if (results.empty())
results = GetProcessMemoryMaps(pid);
if (results.empty())
return false;
dump->memory_maps = std::move(maps);
dump->memory_maps = std::move(results);
return true;
}
......
......@@ -20,15 +20,22 @@ namespace memory_instrumentation {
class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT OSMetrics {
public:
static bool FillOSMemoryDump(base::ProcessId pid, mojom::RawOSMemDump* dump);
static bool FillProcessMemoryMaps(base::ProcessId, mojom::RawOSMemDump*);
static bool FillProcessMemoryMaps(base::ProcessId,
mojom::MemoryMapOption,
mojom::RawOSMemDump*);
private:
FRIEND_TEST_ALL_PREFIXES(OSMetricsTest, ParseProcSmaps);
FRIEND_TEST_ALL_PREFIXES(OSMetricsTest, TestWinModuleReading);
FRIEND_TEST_ALL_PREFIXES(OSMetricsTest, TestMachOReading);
FRIEND_TEST_ALL_PREFIXES(profiling::ProfilingJsonExporterTest, MemoryMaps);
static std::vector<mojom::VmRegionPtr> GetProcessMemoryMaps(base::ProcessId);
#if defined(OS_MACOSX)
static std::vector<mojom::VmRegionPtr> GetProcessModules(base::ProcessId);
#endif
#if defined(OS_LINUX) || defined(OS_ANDROID)
static void SetProcSmapsForTesting(FILE*);
#endif // defined(OS_LINUX)
......
......@@ -255,4 +255,19 @@ std::vector<mojom::VmRegionPtr> OSMetrics::GetProcessMemoryMaps(
return maps;
}
std::vector<mojom::VmRegionPtr> OSMetrics::GetProcessModules(
base::ProcessId pid) {
std::vector<mojom::VmRegionPtr> maps;
std::vector<VMRegion> dyld_regions;
if (!GetDyldRegions(&dyld_regions))
return maps;
for (VMRegion& region : dyld_regions) {
maps.push_back(VMRegion::New(region));
}
return maps;
}
} // namespace memory_instrumentation
......@@ -251,8 +251,9 @@ TEST(OSMetricsTest, TestWinModuleReading) {
#endif // defined(OS_WIN)
#if defined(OS_MACOSX)
TEST(OSMetricsTest, TestMachOReading) {
auto maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessId);
namespace {
void CheckMachORegions(const std::vector<mojom::VmRegionPtr>& maps) {
uint32_t size = 100;
char full_path[size];
int result = _NSGetExecutablePath(full_path, &size);
......@@ -280,6 +281,15 @@ TEST(OSMetricsTest, TestMachOReading) {
EXPECT_TRUE(found_components_unittests);
EXPECT_TRUE(found_appkit);
}
} // namespace
TEST(OSMetricsTest, TestMachOReading) {
auto maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessId);
CheckMachORegions(maps);
maps = OSMetrics::GetProcessModules(base::kNullProcessId);
CheckMachORegions(maps);
}
#endif // defined(OS_MACOSX)
} // namespace memory_instrumentation
......@@ -38,6 +38,19 @@ enum HeapProfilingMode {
NATIVE_STACK
};
enum MemoryMapOption {
// Do not fetch any information about mapped regions in the virtual address
// space.
NONE,
// Only fetch information on code modules, e.g. Chrome Binary, system
// libraries.
MODULES,
// Fetch information for every single mapped region.
FULL
};
// These structs are internal only (only for the communication between
// the service and the ClientProcess library).
// See corresponding types in //base/trace_event for comments.
......@@ -213,7 +226,7 @@ interface ClientProcess {
// On Linux we call this once on the browser process ClientProcess passing
// the pids for all processes.
// See crbug.com/461788
RequestOSMemoryDump(bool want_mmaps, array<mojo_base.mojom.ProcessId> pids) =>
RequestOSMemoryDump(MemoryMapOption option, array<mojo_base.mojom.ProcessId> pids) =>
(bool success, map<mojo_base.mojom.ProcessId, RawOSMemDump> dumps);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment