[memory-infra] Don't report PSS or mapping count for footprint requests
The CLs https://crrev.com/c/6148597 and https://crrev.com/c/6347824 added additional metrics to the RawOSMemDump and populated them on the Linux platform. These metrics are populated for all requests to OSMetrics::FillOSMemoryDump even if they are totally ignored by the caller. This code path is used not only for metrics collection, but also the generation of the private memory footprint for the TaskManagerImpl which does not require such information. The TaskManagerImpl polls for RequestPrivateMemoryFootprint which issues a memory_footprint_only request to MemoryInstrumentation. We now take an additional vector of flags which determine which parts of the RawOSMemDump are populated. When memory_footprint_only is true this vector is empty and when it's true we add all of the enum options which populates the count_mappings and pss fields. In the future this set of flags may be extended to support more options such as native_library_pages_bitmap. Then these can be used to standardize the request for memory dumps (see https://crbug.com/417455299). Bug: 417080394 Change-Id: Iab9a4705b42dd2d571e1ff6370a73235d5e0f843 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6535692 Reviewed-by: Joe Mason <joenotcharles@google.com> Reviewed-by: Francois Pierre Doray <fdoray@chromium.org> Commit-Queue: Joe Mason <joenotcharles@google.com> Cr-Commit-Position: refs/heads/main@{#1460382}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
a3a4cac570
commit
b26436faa4
content/browser/renderer_host
services/resource_coordinator
memory_instrumentation
public
cpp
memory_instrumentation
mojom
memory_instrumentation
@ -5291,11 +5291,11 @@ uint64_t RenderProcessHostImpl::GetPrivateMemoryFootprint() {
|
||||
memory_instrumentation::mojom::PlatformPrivateFootprint::New();
|
||||
#if BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_IOS_TVOS)
|
||||
bool success = memory_instrumentation::OSMetrics::FillOSMemoryDump(
|
||||
GetProcess().Handle(), ChildProcessTaskPortProvider::GetInstance(),
|
||||
GetProcess().Handle(), {}, ChildProcessTaskPortProvider::GetInstance(),
|
||||
dump.get());
|
||||
#else
|
||||
bool success = memory_instrumentation::OSMetrics::FillOSMemoryDump(
|
||||
GetProcess().Handle(), dump.get());
|
||||
GetProcess().Handle(), {}, dump.get());
|
||||
#endif
|
||||
|
||||
// Failed to get private memory for the process, e.g. the process has died.
|
||||
|
@ -178,8 +178,9 @@ class MockClientProcess : public mojom::ClientProcess {
|
||||
std::move(callback).Run(true, args.dump_guid, std::move(pmd));
|
||||
}));
|
||||
|
||||
ON_CALL(*this, RequestOSMemoryDumpMock(_, _, _))
|
||||
ON_CALL(*this, RequestOSMemoryDumpMock(_, _, _, _))
|
||||
.WillByDefault(Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId> pids,
|
||||
RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
@ -194,8 +195,9 @@ class MockClientProcess : public mojom::ClientProcess {
|
||||
MOCK_METHOD2(RequestChromeMemoryDumpMock,
|
||||
void(const MemoryDumpRequestArgs& args,
|
||||
RequestChromeMemoryDumpCallback& callback));
|
||||
MOCK_METHOD3(RequestOSMemoryDumpMock,
|
||||
MOCK_METHOD4(RequestOSMemoryDumpMock,
|
||||
void(mojom::MemoryMapOption option,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& args,
|
||||
RequestOSMemoryDumpCallback& callback));
|
||||
|
||||
@ -205,9 +207,10 @@ class MockClientProcess : public mojom::ClientProcess {
|
||||
RequestChromeMemoryDumpMock(args, callback);
|
||||
}
|
||||
void RequestOSMemoryDump(mojom::MemoryMapOption option,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& args,
|
||||
RequestOSMemoryDumpCallback callback) override {
|
||||
RequestOSMemoryDumpMock(option, args, callback);
|
||||
RequestOSMemoryDumpMock(option, flags, args, callback);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -389,10 +392,12 @@ TEST_F(CoordinatorImplTest, MissingOsDump) {
|
||||
NiceMock<MockClientProcess> client_process(this, 1,
|
||||
mojom::ProcessType::BROWSER);
|
||||
|
||||
EXPECT_CALL(client_process, RequestOSMemoryDumpMock(_, _, _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(client_process, RequestOSMemoryDumpMock(_, _, _, _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
@ -455,31 +460,38 @@ TEST_F(CoordinatorImplTest, TimeOutStuckChildMultiProcess) {
|
||||
// On Linux, all memory dumps come from the browser client. On all other
|
||||
// platforms, they are expected to come from each individual client.
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
EXPECT_CALL(browser_client,
|
||||
RequestOSMemoryDumpMock(
|
||||
_, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(
|
||||
browser_client,
|
||||
RequestOSMemoryDumpMock(
|
||||
_, _, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[kBrowserPid] = FillRawOSDump(kBrowserPid);
|
||||
results[kRendererPid] = FillRawOSDump(kRendererPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, _)).Times(0);
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, _, _)).Times(0);
|
||||
#else
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = FillRawOSDump(kBrowserPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = FillRawOSDump(kRendererPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
@ -633,10 +645,12 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
|
||||
}));
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
EXPECT_CALL(browser_client,
|
||||
RequestOSMemoryDumpMock(_, AllOf(Contains(1), Contains(2)), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
RequestOSMemoryDumpMock(_, _, AllOf(Contains(1), Contains(2)), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[1] = mojom::RawOSMemDump::New();
|
||||
results[1]->resident_set_kb = 1;
|
||||
@ -648,12 +662,14 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
|
||||
results[2]->resident_set_kb = 2;
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, _)).Times(0);
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, _, _)).Times(0);
|
||||
#else
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = mojom::RawOSMemDump::New();
|
||||
results[0]->platform_private_footprint =
|
||||
@ -661,10 +677,12 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
|
||||
results[0]->resident_set_kb = 1;
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = mojom::RawOSMemDump::New();
|
||||
results[0]->platform_private_footprint =
|
||||
@ -717,31 +735,38 @@ 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 BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
EXPECT_CALL(browser_client,
|
||||
RequestOSMemoryDumpMock(
|
||||
_, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(
|
||||
browser_client,
|
||||
RequestOSMemoryDumpMock(
|
||||
_, _, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[kBrowserPid] = FillRawOSDump(kBrowserPid);
|
||||
results[kRendererPid] = FillRawOSDump(kRendererPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, _)).Times(0);
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, _, _)).Times(0);
|
||||
#else
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = FillRawOSDump(kBrowserPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(renderer_client, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = FillRawOSDump(kRendererPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
@ -881,49 +906,61 @@ TEST_F(CoordinatorImplTest, DumpByPidSuccess) {
|
||||
// On Linux, all memory dumps come from the browser client. On all other
|
||||
// platforms, they are expected to come from each individual client.
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
EXPECT_CALL(client_process_1, RequestOSMemoryDumpMock(_, _, _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(client_process_1, RequestOSMemoryDumpMock(_, _, _, _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[kBrowserPid] = FillRawOSDump(kBrowserPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[kRendererPid] = FillRawOSDump(kRendererPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[kGpuPid] = FillRawOSDump(kGpuPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
#else
|
||||
EXPECT_CALL(client_process_1, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(client_process_1, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = FillRawOSDump(kBrowserPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(client_process_2, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(client_process_2, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = FillRawOSDump(kRendererPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
EXPECT_CALL(client_process_3, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(client_process_3, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = FillRawOSDump(kGpuPid);
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
@ -1009,10 +1046,12 @@ TEST_F(CoordinatorImplTest, GlobalDumpWithSubTrees) {
|
||||
std::move(callback).Run(true, args.dump_guid, std::move(pmd));
|
||||
}));
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, Contains(1), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, _, Contains(1), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[1] = mojom::RawOSMemDump::New();
|
||||
results[1]->resident_set_kb = 1;
|
||||
@ -1021,10 +1060,12 @@ TEST_F(CoordinatorImplTest, GlobalDumpWithSubTrees) {
|
||||
std::move(callback).Run(true, std::move(results));
|
||||
}));
|
||||
#else
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, Contains(0), _))
|
||||
.WillOnce(Invoke(
|
||||
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
EXPECT_CALL(browser_client, RequestOSMemoryDumpMock(_, _, Contains(0), _))
|
||||
.WillOnce(
|
||||
Invoke([](mojom::MemoryMapOption,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
MockClientProcess::RequestOSMemoryDumpCallback& callback) {
|
||||
base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
|
||||
results[0] = mojom::RawOSMemDump::New();
|
||||
results[0]->platform_private_footprint =
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
#include "services/resource_coordinator/memory_instrumentation/queued_request.h"
|
||||
|
||||
#include "base/containers/to_vector.h"
|
||||
#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h"
|
||||
|
||||
namespace memory_instrumentation {
|
||||
|
||||
QueuedRequest::Args::Args(MemoryDumpType dump_type,
|
||||
@ -51,6 +54,13 @@ base::trace_event::MemoryDumpRequestArgs QueuedRequest::GetRequestArgs() {
|
||||
return request_args;
|
||||
}
|
||||
|
||||
std::vector<mojom::MemDumpFlags> QueuedRequest::memory_dump_flags() const {
|
||||
if (!args.memory_footprint_only) {
|
||||
return base::ToVector(OSMetrics::MemDumpFlagSet::All());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QueuedVmRegionRequest::Response::Response() = default;
|
||||
QueuedVmRegionRequest::Response::~Response() = default;
|
||||
|
||||
|
@ -93,6 +93,8 @@ struct QueuedRequest {
|
||||
: mojom::MemoryMapOption::NONE;
|
||||
}
|
||||
|
||||
std::vector<mojom::MemDumpFlags> memory_dump_flags() const;
|
||||
|
||||
bool should_return_summaries() const {
|
||||
return args.dump_type == base::trace_event::MemoryDumpType::kSummaryOnly;
|
||||
}
|
||||
|
@ -224,9 +224,9 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
|
||||
// so ask each process to do so Linux is special see below.
|
||||
#if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
|
||||
request->pending_responses.insert({client_info.pid, ResponseType::kOSDump});
|
||||
client->RequestOSMemoryDump(request->memory_map_option(),
|
||||
{base::kNullProcessId},
|
||||
base::BindOnce(os_callback, client_info.pid));
|
||||
client->RequestOSMemoryDump(
|
||||
request->memory_map_option(), request->memory_dump_flags(),
|
||||
{base::kNullProcessId}, base::BindOnce(os_callback, client_info.pid));
|
||||
#endif // !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
|
||||
|
||||
// If we are in the single pid case, then we've already found the only
|
||||
@ -259,7 +259,8 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
|
||||
request->pending_responses.insert(
|
||||
{browser_client_pid, ResponseType::kOSDump});
|
||||
auto callback = base::BindOnce(os_callback, browser_client_pid);
|
||||
browser_client->RequestOSMemoryDump(request->memory_map_option(), pids,
|
||||
browser_client->RequestOSMemoryDump(request->memory_map_option(),
|
||||
request->memory_dump_flags(), pids,
|
||||
std::move(callback));
|
||||
}
|
||||
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
@ -302,7 +303,7 @@ void QueuedRequestDispatcher::SetUpAndDispatchVmRegionRequest(
|
||||
request->pending_responses.insert(browser_client_pid);
|
||||
request->responses[browser_client_pid].process_id = browser_client_pid;
|
||||
auto callback = base::BindOnce(os_callback, browser_client_pid);
|
||||
browser_client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
|
||||
browser_client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES, {},
|
||||
desired_pids, std::move(callback));
|
||||
#else
|
||||
for (const auto& client_info : clients) {
|
||||
@ -312,7 +313,7 @@ void QueuedRequestDispatcher::SetUpAndDispatchVmRegionRequest(
|
||||
request->responses[client_info.pid].process_id = client_info.pid;
|
||||
request->responses[client_info.pid].service_name =
|
||||
client_info.service_name;
|
||||
client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
|
||||
client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES, {},
|
||||
{base::kNullProcessId},
|
||||
base::BindOnce(os_callback, client_info.pid));
|
||||
}
|
||||
|
@ -20,6 +20,16 @@
|
||||
|
||||
namespace memory_instrumentation {
|
||||
|
||||
struct ClientProcessImpl::OSMemoryDumpArgs {
|
||||
OSMemoryDumpArgs();
|
||||
OSMemoryDumpArgs(OSMemoryDumpArgs&&);
|
||||
~OSMemoryDumpArgs();
|
||||
mojom::MemoryMapOption mmap_option;
|
||||
OSMetrics::MemDumpFlagSet flags;
|
||||
std::vector<base::ProcessId> pids;
|
||||
RequestOSMemoryDumpCallback callback;
|
||||
};
|
||||
|
||||
// static
|
||||
void ClientProcessImpl::CreateInstance(
|
||||
mojo::PendingReceiver<mojom::ClientProcess> receiver,
|
||||
@ -144,12 +154,16 @@ void ClientProcessImpl::RequestGlobalMemoryDump_NoCallback(
|
||||
|
||||
void ClientProcessImpl::RequestOSMemoryDump(
|
||||
mojom::MemoryMapOption mmap_option,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& pids,
|
||||
RequestOSMemoryDumpCallback callback) {
|
||||
OSMemoryDumpArgs args;
|
||||
args.mmap_option = mmap_option;
|
||||
args.pids = pids;
|
||||
args.callback = std::move(callback);
|
||||
for (const auto& flag : flags) {
|
||||
args.flags.Put(flag);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// If the most recent chrome memory dump hasn't finished, wait for that to
|
||||
@ -173,7 +187,8 @@ void ClientProcessImpl::PerformOSMemoryDump(OSMemoryDumpArgs args) {
|
||||
auto handle = base::Process::Open(pid).Handle();
|
||||
mojom::RawOSMemDumpPtr result = mojom::RawOSMemDump::New();
|
||||
result->platform_private_footprint = mojom::PlatformPrivateFootprint::New();
|
||||
bool success = OSMetrics::FillOSMemoryDump(handle, result.get());
|
||||
bool success =
|
||||
OSMetrics::FillOSMemoryDump(handle, args.flags, result.get());
|
||||
if (args.mmap_option != mojom::MemoryMapOption::NONE) {
|
||||
success = success && OSMetrics::FillProcessMemoryMaps(
|
||||
handle, args.mmap_option, result.get());
|
||||
|
@ -67,17 +67,11 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
|
||||
|
||||
// mojom::ClientProcess implementation. The Coordinator calls this.
|
||||
void RequestOSMemoryDump(mojom::MemoryMapOption mmap_option,
|
||||
const std::vector<mojom::MemDumpFlags>& flags,
|
||||
const std::vector<base::ProcessId>& ids,
|
||||
RequestOSMemoryDumpCallback callback) override;
|
||||
|
||||
struct OSMemoryDumpArgs {
|
||||
OSMemoryDumpArgs();
|
||||
OSMemoryDumpArgs(OSMemoryDumpArgs&&);
|
||||
~OSMemoryDumpArgs();
|
||||
mojom::MemoryMapOption mmap_option;
|
||||
std::vector<base::ProcessId> pids;
|
||||
RequestOSMemoryDumpCallback callback;
|
||||
};
|
||||
struct OSMemoryDumpArgs;
|
||||
void PerformOSMemoryDump(OSMemoryDumpArgs args);
|
||||
|
||||
// Map containing pending chrome memory callbacks indexed by dump guid.
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/containers/enum_set.h"
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/process/process_metrics.h"
|
||||
@ -40,14 +41,21 @@ namespace memory_instrumentation {
|
||||
class COMPONENT_EXPORT(
|
||||
RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) OSMetrics {
|
||||
public:
|
||||
using MemDumpFlagSet =
|
||||
base::EnumSet<mojom::MemDumpFlags,
|
||||
mojom::MemDumpFlags::MEM_DUMP_COUNT_MAPPINGS,
|
||||
mojom::MemDumpFlags::kMaxValue>;
|
||||
|
||||
// Fills |dump| with memory information about |handle|. See class comments for
|
||||
// restrictions on |handle|. |dump.platform_private_footprint| must be
|
||||
// allocated before calling this function. If |handle| is null, the handle of
|
||||
// the current process is used
|
||||
static bool FillOSMemoryDump(base::ProcessHandle handle,
|
||||
const MemDumpFlagSet& flags,
|
||||
mojom::RawOSMemDump* dump);
|
||||
#if BUILDFLAG(IS_APPLE)
|
||||
static bool FillOSMemoryDump(base::ProcessHandle handle,
|
||||
const MemDumpFlagSet& flags,
|
||||
base::PortProvider* port_provider,
|
||||
mojom::RawOSMemDump* dump);
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@ namespace memory_instrumentation {
|
||||
|
||||
// static
|
||||
bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
|
||||
const MemDumpFlagSet& flags,
|
||||
mojom::RawOSMemDump* dump) {
|
||||
auto info = GetMemoryInfo(handle);
|
||||
if (!info.has_value()) {
|
||||
|
@ -329,6 +329,7 @@ void OSMetrics::SetProcSmapsForTesting(FILE* f) {
|
||||
|
||||
// static
|
||||
bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
|
||||
const MemDumpFlagSet& flags,
|
||||
mojom::RawOSMemDump* dump) {
|
||||
auto info = GetMemoryInfo(handle);
|
||||
if (!info.has_value()) {
|
||||
@ -341,8 +342,12 @@ bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
|
||||
base::saturated_cast<uint32_t>(info->resident_set_bytes / 1024);
|
||||
dump->peak_resident_set_kb = GetPeakResidentSetSize(handle);
|
||||
dump->is_peak_rss_resettable = ResetPeakRSSIfPossible(handle);
|
||||
dump->mappings_count = CountMappings(handle);
|
||||
GetSmapsRollup(&dump->pss_kb, &dump->swap_pss_kb);
|
||||
if (flags.Has(mojom::MemDumpFlags::MEM_DUMP_COUNT_MAPPINGS)) {
|
||||
dump->mappings_count = CountMappings(handle);
|
||||
}
|
||||
if (flags.Has(mojom::MemDumpFlags::MEM_DUMP_PSS)) {
|
||||
GetSmapsRollup(&dump->pss_kb, &dump->swap_pss_kb);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
|
||||
|
@ -227,16 +227,18 @@ void AddRegionByteStats(VMRegion* dest, const VMRegion& source) {
|
||||
|
||||
// static
|
||||
bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
|
||||
const MemDumpFlagSet& flags,
|
||||
mojom::RawOSMemDump* dump) {
|
||||
auto current_handle = base::GetCurrentProcessHandle();
|
||||
if (handle != base::kNullProcessId && handle != current_handle) {
|
||||
return false;
|
||||
}
|
||||
return FillOSMemoryDump(current_handle, nullptr, dump);
|
||||
return FillOSMemoryDump(current_handle, flags, nullptr, dump);
|
||||
}
|
||||
|
||||
// static
|
||||
bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
|
||||
const MemDumpFlagSet& flags,
|
||||
base::PortProvider* port_provider,
|
||||
mojom::RawOSMemDump* dump) {
|
||||
auto process_metrics =
|
||||
|
@ -164,7 +164,8 @@ TEST(OSMetricsTest, GivesNonZeroResults) {
|
||||
base::ProcessHandle handle = base::kNullProcessHandle;
|
||||
mojom::RawOSMemDump dump;
|
||||
dump.platform_private_footprint = mojom::PlatformPrivateFootprint::New();
|
||||
EXPECT_TRUE(OSMetrics::FillOSMemoryDump(handle, &dump));
|
||||
OSMetrics::MemDumpFlagSet flags = OSMetrics::MemDumpFlagSet::All();
|
||||
EXPECT_TRUE(OSMetrics::FillOSMemoryDump(handle, flags, &dump));
|
||||
EXPECT_TRUE(dump.platform_private_footprint);
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
|
||||
BUILDFLAG(IS_FUCHSIA)
|
||||
@ -286,7 +287,10 @@ TEST(OSMetricsTest, GetMappedAndResidentPages) {
|
||||
TEST(OSMetricsTest, CountMappings) {
|
||||
mojom::RawOSMemDump dump;
|
||||
dump.platform_private_footprint = mojom::PlatformPrivateFootprint::New();
|
||||
ASSERT_TRUE(OSMetrics::FillOSMemoryDump(base::kNullProcessHandle, &dump));
|
||||
OSMetrics::MemDumpFlagSet flags = {
|
||||
mojom::MemDumpFlags::MEM_DUMP_COUNT_MAPPINGS};
|
||||
ASSERT_TRUE(
|
||||
OSMetrics::FillOSMemoryDump(base::kNullProcessHandle, flags, &dump));
|
||||
uint32_t mappings_count = dump.mappings_count;
|
||||
EXPECT_GT(dump.mappings_count, 0u);
|
||||
|
||||
@ -306,12 +310,20 @@ TEST(OSMetricsTest, CountMappings) {
|
||||
mprotect(reinterpret_cast<void*>(start), page_size, PROT_NONE));
|
||||
}
|
||||
|
||||
ASSERT_TRUE(OSMetrics::FillOSMemoryDump(base::kNullProcessHandle, &dump));
|
||||
ASSERT_TRUE(
|
||||
OSMetrics::FillOSMemoryDump(base::kNullProcessHandle, flags, &dump));
|
||||
EXPECT_GT(dump.mappings_count, mappings_count);
|
||||
|
||||
munmap(addr, kPageCount * page_size);
|
||||
}
|
||||
|
||||
TEST(OSMetricsTest, CountMappingsDisabled) {
|
||||
mojom::RawOSMemDump dump;
|
||||
dump.platform_private_footprint = mojom::PlatformPrivateFootprint::New();
|
||||
ASSERT_TRUE(OSMetrics::FillOSMemoryDump(base::kNullProcessHandle, {}, &dump));
|
||||
EXPECT_EQ(dump.mappings_count, 0u);
|
||||
}
|
||||
|
||||
TEST(OSMetricsTest, Pss) {
|
||||
// Some older Android devices may not support this, so skip the test in those
|
||||
// cases.
|
||||
@ -321,13 +333,22 @@ TEST(OSMetricsTest, Pss) {
|
||||
|
||||
mojom::RawOSMemDump dump;
|
||||
dump.platform_private_footprint = mojom::PlatformPrivateFootprint::New();
|
||||
ASSERT_TRUE(OSMetrics::FillOSMemoryDump(base::kNullProcessHandle, &dump));
|
||||
ASSERT_TRUE(OSMetrics::FillOSMemoryDump(
|
||||
base::kNullProcessHandle, {mojom::MemDumpFlags::MEM_DUMP_PSS}, &dump));
|
||||
uint32_t pss = dump.pss_kb;
|
||||
|
||||
// We don't know the exact value here, but it should be greater than 0.
|
||||
EXPECT_GT(pss, 0u);
|
||||
}
|
||||
|
||||
TEST(OSMetricsTest, PssDisabled) {
|
||||
mojom::RawOSMemDump dump;
|
||||
dump.platform_private_footprint = mojom::PlatformPrivateFootprint::New();
|
||||
ASSERT_TRUE(OSMetrics::FillOSMemoryDump(base::kNullProcessHandle, {}, &dump));
|
||||
EXPECT_EQ(dump.pss_kb, 0u);
|
||||
EXPECT_EQ(dump.swap_pss_kb, 0u);
|
||||
}
|
||||
|
||||
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
|
||||
// BUILDFLAG(IS_ANDROID)
|
||||
|
||||
|
@ -41,6 +41,7 @@ std::string MakeDebugID(const GUID& guid, DWORD age) {
|
||||
|
||||
// static
|
||||
bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
|
||||
const MemDumpFlagSet& flags,
|
||||
mojom::RawOSMemDump* dump) {
|
||||
auto info = GetMemoryInfo(handle);
|
||||
if (!info.has_value()) {
|
||||
|
@ -51,6 +51,14 @@ enum MemoryMapOption {
|
||||
FULL,
|
||||
};
|
||||
|
||||
enum MemDumpFlags {
|
||||
// On Linux platforms, populate the mappings_count field of RawOSMemDump.
|
||||
MEM_DUMP_COUNT_MAPPINGS = 0,
|
||||
// On Linux platforms, populate the pss_kb and swap_pss_kb fields of
|
||||
// RawOSMemDump.
|
||||
MEM_DUMP_PSS = 1,
|
||||
};
|
||||
|
||||
// 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.
|
||||
@ -295,7 +303,9 @@ interface ClientProcess {
|
||||
// the pids for all processes.
|
||||
// See crbug.com/461788
|
||||
RequestOSMemoryDump(
|
||||
MemoryMapOption option, array<mojo_base.mojom.ProcessId> pids)
|
||||
MemoryMapOption option,
|
||||
array<MemDumpFlags> flags,
|
||||
array<mojo_base.mojom.ProcessId> pids)
|
||||
=> (bool success, map<mojo_base.mojom.ProcessId, RawOSMemDump> dumps);
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user