Commit 482fcec0 authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

[reland] Adds support for renderer memory heartbeat metric to WebView

Specifically Memory.Renderer.PrivateMemoryFootprint. This refactors existing
code in hopes of sharing names and some portions of the logic. This doesn't
include Memory.Browser as it's not really under our control (I'm starting an
email thread on this one). Logging is only enabled for the non-single process
case.

This patch is exactly the same as the first patch. I fixed the reason that
lead to the revert here: https://chromium-review.googlesource.com/c/chromium/src/+/1716584

BUG=981102
TEST=covered by integration tests
TBR=bcwhite@chromium.org, changwan@chromium.org, chrisha@chromium.org

Change-Id: Iabb1193481600c208fe56207aaef01d1fd3b9401
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1726410Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarBrian White <bcwhite@chromium.org>
Reviewed-by: default avatarChangwan Ryu <changwan@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#682416}
parent 62a338dc
...@@ -578,6 +578,8 @@ source_set("common") { ...@@ -578,6 +578,8 @@ source_set("common") {
"browser/js_java_interaction/js_api_handler_factory.h", "browser/js_java_interaction/js_api_handler_factory.h",
"browser/js_java_interaction/js_java_configurator_host.cc", "browser/js_java_interaction/js_java_configurator_host.cc",
"browser/js_java_interaction/js_java_configurator_host.h", "browser/js_java_interaction/js_java_configurator_host.h",
"browser/memory_metrics_logger.cc",
"browser/memory_metrics_logger.h",
"browser/net/android_stream_reader_url_request_job.cc", "browser/net/android_stream_reader_url_request_job.cc",
"browser/net/android_stream_reader_url_request_job.h", "browser/net/android_stream_reader_url_request_job.h",
"browser/net/aw_cookie_change_dispatcher_wrapper.cc", "browser/net/aw_cookie_change_dispatcher_wrapper.cc",
...@@ -771,6 +773,8 @@ source_set("common") { ...@@ -771,6 +773,8 @@ source_set("common") {
"//net:extras", "//net:extras",
"//printing", "//printing",
"//services/preferences/tracked:tracked", "//services/preferences/tracked:tracked",
"//services/resource_coordinator/public/cpp/memory_instrumentation",
"//services/resource_coordinator/public/cpp/memory_instrumentation:browser",
"//services/service_manager/public/cpp", "//services/service_manager/public/cpp",
"//storage/browser", "//storage/browser",
"//storage/common", "//storage/common",
......
...@@ -58,6 +58,7 @@ include_rules = [ ...@@ -58,6 +58,7 @@ include_rules = [
"+printing", "+printing",
"+services/network/public", "+services/network/public",
"+services/resource_coordinator/public/cpp",
"+services/service_manager/public/cpp", "+services/service_manager/public/cpp",
# network service related unit tests # network service related unit tests
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "android_webview/browser/aw_browser_terminator.h" #include "android_webview/browser/aw_browser_terminator.h"
#include "android_webview/browser/aw_content_browser_client.h" #include "android_webview/browser/aw_content_browser_client.h"
#include "android_webview/browser/aw_metrics_service_client.h" #include "android_webview/browser/aw_metrics_service_client.h"
#include "android_webview/browser/memory_metrics_logger.h"
#include "android_webview/browser/net/aw_network_change_notifier_factory.h" #include "android_webview/browser/net/aw_network_change_notifier_factory.h"
#include "android_webview/common/aw_descriptors.h" #include "android_webview/common/aw_descriptors.h"
#include "android_webview/common/aw_paths.h" #include "android_webview/common/aw_paths.h"
...@@ -123,6 +124,7 @@ void AwBrowserMainParts::PreMainMessageLoopRun() { ...@@ -123,6 +124,7 @@ void AwBrowserMainParts::PreMainMessageLoopRun() {
AwBrowserContext* context = browser_client_->InitBrowserContext(); AwBrowserContext* context = browser_client_->InitBrowserContext();
context->PreMainMessageLoopRun(); context->PreMainMessageLoopRun();
content::RenderFrameHost::AllowInjectingJavaScript(); content::RenderFrameHost::AllowInjectingJavaScript();
metrics_logger_ = std::make_unique<MemoryMetricsLogger>();
} }
bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) { bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) {
......
...@@ -15,8 +15,9 @@ ...@@ -15,8 +15,9 @@
namespace android_webview { namespace android_webview {
class AwContentBrowserClient;
class AwBrowserProcess; class AwBrowserProcess;
class AwContentBrowserClient;
class MemoryMetricsLogger;
class AwBrowserMainParts : public content::BrowserMainParts { class AwBrowserMainParts : public content::BrowserMainParts {
public: public:
...@@ -36,6 +37,8 @@ class AwBrowserMainParts : public content::BrowserMainParts { ...@@ -36,6 +37,8 @@ class AwBrowserMainParts : public content::BrowserMainParts {
AwContentBrowserClient* browser_client_; AwContentBrowserClient* browser_client_;
std::unique_ptr<MemoryMetricsLogger> metrics_logger_;
std::unique_ptr<AwBrowserProcess> browser_process_; std::unique_ptr<AwBrowserProcess> browser_process_;
DISALLOW_COPY_AND_ASSIGN(AwBrowserMainParts); DISALLOW_COPY_AND_ASSIGN(AwBrowserMainParts);
......
// Copyright 2019 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 "android_webview/browser/memory_metrics_logger.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_functions.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
using memory_instrumentation::GetPrivateFootprintHistogramName;
using memory_instrumentation::HistogramProcessType;
namespace android_webview {
namespace {
MemoryMetricsLogger* g_instance = nullptr;
// Called once the metrics have been determined. Does the actual logging.
void RecordMemoryMetricsImpl(
MemoryMetricsLogger::RecordCallback done_callback,
bool success,
std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump) {
if (!success) {
if (done_callback)
std::move(done_callback).Run(false);
return;
}
for (const auto& process_dump : dump->process_dumps()) {
switch (process_dump.process_type()) {
case memory_instrumentation::mojom::ProcessType::BROWSER: {
MEMORY_METRICS_HISTOGRAM_MB(
GetPrivateFootprintHistogramName(HistogramProcessType::kBrowser),
process_dump.os_dump().private_footprint_kb / 1024);
break;
}
case memory_instrumentation::mojom::ProcessType::RENDERER: {
// On the desktop this may be attributed to an 'extension', but as
// android doesn't support extensions there is no checking.
MEMORY_METRICS_HISTOGRAM_MB(
GetPrivateFootprintHistogramName(HistogramProcessType::kRenderer),
process_dump.os_dump().private_footprint_kb / 1024);
break;
}
// WebView only supports the browser and possibly renderer process.
case memory_instrumentation::mojom::ProcessType::GPU:
FALLTHROUGH;
case memory_instrumentation::mojom::ProcessType::ARC:
FALLTHROUGH;
case memory_instrumentation::mojom::ProcessType::UTILITY:
FALLTHROUGH;
case memory_instrumentation::mojom::ProcessType::PLUGIN:
FALLTHROUGH;
case memory_instrumentation::mojom::ProcessType::OTHER:
NOTREACHED();
break;
}
}
if (done_callback)
std::move(done_callback).Run(true);
}
} // namespace
// State is used to trigger logging to stop. State is accessed on both the main
// thread and the background task runner.
struct MemoryMetricsLogger::State : public base::RefCountedThreadSafe<State> {
State() = default;
// MemoryInstrumentation requires a SequencedTaskRunner.
scoped_refptr<base::SequencedTaskRunner> task_runner;
bool stop_logging = false;
private:
friend class base::RefCountedThreadSafe<State>;
~State() = default;
DISALLOW_COPY_AND_ASSIGN(State);
};
MemoryMetricsLogger::MemoryMetricsLogger()
: state_(base::MakeRefCounted<State>()) {
g_instance = this;
state_->task_runner = base::CreateSequencedTaskRunner({base::ThreadPool()});
state_->task_runner->PostTask(
FROM_HERE,
base::BindOnce(&MemoryMetricsLogger::RecordMemoryMetricsAfterDelay,
state_));
}
MemoryMetricsLogger::~MemoryMetricsLogger() {
g_instance = nullptr;
state_->stop_logging = true;
}
// static
MemoryMetricsLogger* MemoryMetricsLogger::GetInstanceForTesting() {
return g_instance;
}
void MemoryMetricsLogger::ScheduleRecordForTesting(
RecordCallback done_callback) {
state_->task_runner->PostTask(
FROM_HERE, base::BindOnce(&MemoryMetricsLogger::RecordMemoryMetrics,
state_, std::move(done_callback)));
}
// static
void MemoryMetricsLogger::RecordMemoryMetricsAfterDelay(
scoped_refptr<State> state) {
if (state->stop_logging)
return;
state->task_runner->PostDelayedTask(
FROM_HERE,
base::BindOnce(&MemoryMetricsLogger::RecordMemoryMetrics, state,
RecordCallback()),
memory_instrumentation::GetDelayForNextMemoryLog());
}
// static
void MemoryMetricsLogger::RecordMemoryMetrics(scoped_refptr<State> state,
RecordCallback done_callback) {
memory_instrumentation::MemoryInstrumentation::GetInstance()
->RequestGlobalDump({}, base::BindOnce(&RecordMemoryMetricsImpl,
std::move(done_callback)));
RecordMemoryMetricsAfterDelay(state);
}
} // namespace android_webview
// Copyright 2019 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.
#ifndef ANDROID_WEBVIEW_BROWSER_MEMORY_METRICS_LOGGER_H_
#define ANDROID_WEBVIEW_BROWSER_MEMORY_METRICS_LOGGER_H_
#include <jni.h>
#include <memory>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
namespace android_webview {
// MemoryMetricsLogger is responsible for logging the memory related heartbeat
// metrics. MemoryMetricsLogger logs metrics at certain intervals for as long
// as it exists.
//
// MemoryMetricsLogger does the logging on a background task runner and stops
// logging once MemoryMetricsLogger is destroyed.
class MemoryMetricsLogger {
public:
using RecordCallback = base::OnceCallback<void(bool)>;
MemoryMetricsLogger();
~MemoryMetricsLogger();
private:
struct State;
friend jboolean JNI_MemoryMetricsLoggerTest_ForceRecordHistograms(
JNIEnv* env);
// Returns the single instance, if one was created.
static MemoryMetricsLogger* GetInstanceForTesting();
// Schedules recording metrics. Runs |done_callback| when done with the
// result of recording metrics. |done_callback| is run on a background
// TaskRunner.
void ScheduleRecordForTesting(RecordCallback done_callback);
// Called on the task runner to record metrics after a delay.
static void RecordMemoryMetricsAfterDelay(scoped_refptr<State> state);
// Requests the memory related metrics and calls
// RecordMemoryMetricsAfterDelay() to schedule another logging call. Runs
// |done_callback| when done.
static void RecordMemoryMetrics(scoped_refptr<State> state,
RecordCallback done_callback);
scoped_refptr<State> state_;
DISALLOW_COPY_AND_ASSIGN(MemoryMetricsLogger);
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_MEMORY_METRICS_LOGGER_H_
// Copyright 2019 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.
package org.chromium.android_webview.test;
import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.MULTI_PROCESS;
import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.SINGLE_PROCESS;
import android.support.test.filters.SmallTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.util.Feature;
/**
* Tests for memory_metrics_logger.cc.
*/
@JNINamespace("android_webview")
@RunWith(AwJUnit4ClassRunner.class)
public class MemoryMetricsLoggerTest {
@Rule
public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
@Before
public void setUp() throws Exception {
TestAwContentsClient contentsClient = new TestAwContentsClient();
AwTestContainerView testContainerView =
mActivityTestRule.createAwTestContainerViewOnMainSync(contentsClient);
mActivityTestRule.loadUrlSync(testContainerView.getAwContents(),
contentsClient.getOnPageFinishedHelper(), "about:blank");
Assert.assertTrue(nativeForceRecordHistograms());
}
@After
public void tearDown() throws Exception {}
@Test
@Feature({"AndroidWebView"})
@OnlyRunIn(MULTI_PROCESS)
@SmallTest
public void testMultiProcessHistograms() throws Throwable {
Assert.assertNotEquals(0,
RecordHistogram.getHistogramTotalCountForTesting(
"Memory.Browser.PrivateMemoryFootprint"));
Assert.assertNotEquals(0,
RecordHistogram.getHistogramTotalCountForTesting(
"Memory.Renderer.PrivateMemoryFootprint"));
}
@Test
@Feature({"AndroidWebView"})
@OnlyRunIn(SINGLE_PROCESS)
@SmallTest
public void testSingleProcessHistograms() throws Throwable {
Assert.assertNotEquals(0,
RecordHistogram.getHistogramTotalCountForTesting(
"Memory.Browser.PrivateMemoryFootprint"));
Assert.assertEquals(0,
RecordHistogram.getHistogramTotalCountForTesting(
"Memory.Renderer.PrivateMemoryFootprint"));
}
/**
* Calls to MemoryMetricsLogger to force recording histograms, returning true on success.
* A value of false means recording failed (most likely because process metrics not available.
*/
public static native boolean nativeForceRecordHistograms();
}
// Copyright 2019 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 "android_webview/test/webview_instrumentation_test_native_jni/MemoryMetricsLoggerTest_jni.h"
#include "android_webview/browser/memory_metrics_logger.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_timeouts.h"
namespace android_webview {
// static
jboolean JNI_MemoryMetricsLoggerTest_ForceRecordHistograms(JNIEnv* env) {
auto* memory_metrics_logger = MemoryMetricsLogger::GetInstanceForTesting();
if (!memory_metrics_logger)
return false;
TestTimeouts::Initialize();
base::test::ScopedTaskEnvironment scoped_task_environment(
base::test::ScopedTaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY);
base::RunLoop run_loop;
bool result = false;
memory_metrics_logger->ScheduleRecordForTesting(
base::BindLambdaForTesting([&](bool success) {
result = success;
run_loop.Quit();
}));
run_loop.Run();
return result;
}
} // namespace android_webview
...@@ -138,6 +138,7 @@ shared_library("libstandalonelibwebviewchromium") { ...@@ -138,6 +138,7 @@ shared_library("libstandalonelibwebviewchromium") {
] ]
ldflags = [ "-Wl,-shared,-Bsymbolic" ] ldflags = [ "-Wl,-shared,-Bsymbolic" ]
deps = [ deps = [
":webview_instrumentation_test_native_jni_impl",
"//android_webview:common", "//android_webview:common",
"//base", "//base",
"//components/heap_profiling:test_support", "//components/heap_profiling:test_support",
...@@ -250,6 +251,7 @@ instrumentation_test_apk("webview_instrumentation_test_apk") { ...@@ -250,6 +251,7 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
"../javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java", "../javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java",
"../javatests/src/org/chromium/android_webview/test/LoadUrlTest.java", "../javatests/src/org/chromium/android_webview/test/LoadUrlTest.java",
"../javatests/src/org/chromium/android_webview/test/MediaAccessPermissionRequestTest.java", "../javatests/src/org/chromium/android_webview/test/MediaAccessPermissionRequestTest.java",
"../javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java",
"../javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java", "../javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java",
"../javatests/src/org/chromium/android_webview/test/OnDiskFileTest.java", "../javatests/src/org/chromium/android_webview/test/OnDiskFileTest.java",
"../javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java", "../javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java",
...@@ -320,6 +322,25 @@ instrumentation_test_apk("webview_instrumentation_test_apk") { ...@@ -320,6 +322,25 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
] ]
} }
generate_jni("webview_instrumentation_test_native_jni") {
sources = [
"../javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java",
]
}
source_set("webview_instrumentation_test_native_jni_impl") {
sources = [
"../javatests/src/org/chromium/android_webview/test/memory_metrics_logger_test.cc",
]
deps = [
":webview_instrumentation_test_native_jni",
"//android_webview:common",
"//base",
"//base/test:test_support",
]
}
test("android_webview_unittests") { test("android_webview_unittests") {
deps = [ deps = [
":android_webview_unittests_assets", ":android_webview_unittests_assets",
......
...@@ -2138,6 +2138,7 @@ jumbo_split_static_library("browser") { ...@@ -2138,6 +2138,7 @@ jumbo_split_static_library("browser") {
"//services/preferences/tracked", "//services/preferences/tracked",
"//services/proxy_resolver/public/mojom", "//services/proxy_resolver/public/mojom",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/resource_coordinator/public/cpp/memory_instrumentation:browser",
"//services/service_manager/public/cpp", "//services/service_manager/public/cpp",
"//services/shape_detection/public/mojom", "//services/shape_detection/public/mojom",
"//services/strings", "//services/strings",
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
#include "ui/base/pointer/pointer_device.h" #include "ui/base/pointer/pointer_device.h"
#include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_switches.h"
#include "ui/display/screen.h" #include "ui/display/screen.h"
...@@ -72,21 +73,12 @@ namespace { ...@@ -72,21 +73,12 @@ namespace {
void RecordMemoryMetrics(); void RecordMemoryMetrics();
// Records memory metrics after a delay, with a fixed mean interval but randomly // Records memory metrics after a delay.
// distributed samples using a poisson process.
void RecordMemoryMetricsAfterDelay() { void RecordMemoryMetricsAfterDelay() {
#if defined(OS_ANDROID) base::PostDelayedTaskWithTraits(
base::TimeDelta mean_time = base::TimeDelta::FromMinutes(5); FROM_HERE, {content::BrowserThread::UI},
#else base::BindOnce(&RecordMemoryMetrics),
base::TimeDelta mean_time = base::TimeDelta::FromMinutes(30); memory_instrumentation::GetDelayForNextMemoryLog());
#endif
// Compute the actual delay before sampling using a Poisson process.
double uniform = base::RandDouble();
base::TimeDelta delay = -std::log(uniform) * mean_time;
base::PostDelayedTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&RecordMemoryMetrics), delay);
} }
// Records memory metrics, and then triggers memory colleciton after a delay. // Records memory metrics, and then triggers memory colleciton after a delay.
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "extensions/buildflags/buildflags.h" #include "extensions/buildflags/buildflags.h"
#include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h" #include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -39,7 +40,11 @@ ...@@ -39,7 +40,11 @@
#endif #endif
using base::trace_event::MemoryAllocatorDump; using base::trace_event::MemoryAllocatorDump;
using memory_instrumentation::GetPrivateFootprintHistogramName;
using memory_instrumentation::GlobalMemoryDump; using memory_instrumentation::GlobalMemoryDump;
using memory_instrumentation::HistogramProcessType;
using memory_instrumentation::HistogramProcessTypeToString;
using memory_instrumentation::kMemoryHistogramPrefix;
using ukm::builders::Memory_Experimental; using ukm::builders::Memory_Experimental;
const base::Feature kMemoryMetricsOldTiming{"MemoryMetricsOldTiming", const base::Feature kMemoryMetricsOldTiming{"MemoryMetricsOldTiming",
...@@ -282,15 +287,10 @@ const Metric kAllocatorDumpNamesForMetrics[] = { ...@@ -282,15 +287,10 @@ const Metric kAllocatorDumpNamesForMetrics[] = {
&Memory_Experimental::SetWebCache_OtherResources}, &Memory_Experimental::SetWebCache_OtherResources},
}; };
#define UMA_PREFIX "Memory."
#define EXPERIMENTAL_UMA_PREFIX "Memory.Experimental." #define EXPERIMENTAL_UMA_PREFIX "Memory.Experimental."
#define VERSION_SUFFIX_NORMAL "2." #define VERSION_SUFFIX_NORMAL "2."
#define VERSION_SUFFIX_SMALL "2.Small." #define VERSION_SUFFIX_SMALL "2.Small."
// Use the values from UMA_HISTOGRAM_MEMORY_LARGE_MB.
#define MEMORY_METRICS_HISTOGRAM_MB(name, value) \
base::UmaHistogramCustomCounts(name, value, 1, 64000, 100)
// Used to measure KB-granularity memory stats. Range is from 1KB to 500,000KB // Used to measure KB-granularity memory stats. Range is from 1KB to 500,000KB
// (500MB). // (500MB).
#define MEMORY_METRICS_HISTOGRAM_KB(name, value) \ #define MEMORY_METRICS_HISTOGRAM_KB(name, value) \
...@@ -303,7 +303,7 @@ void EmitProcessUkm(const Metric& item, ...@@ -303,7 +303,7 @@ void EmitProcessUkm(const Metric& item,
(builder->*(item.ukm_setter))(value); (builder->*(item.ukm_setter))(value);
} }
void EmitProcessUma(const char* process_name, void EmitProcessUma(HistogramProcessType process_type,
const Metric& item, const Metric& item,
uint64_t value) { uint64_t value) {
std::string uma_name; std::string uma_name;
...@@ -317,8 +317,9 @@ void EmitProcessUma(const char* process_name, ...@@ -317,8 +317,9 @@ void EmitProcessUma(const char* process_name,
} else { } else {
const char* version_suffix = const char* version_suffix =
item.is_large_metric ? VERSION_SUFFIX_NORMAL : VERSION_SUFFIX_SMALL; item.is_large_metric ? VERSION_SUFFIX_NORMAL : VERSION_SUFFIX_SMALL;
uma_name = std::string(EXPERIMENTAL_UMA_PREFIX) + process_name + uma_name = std::string(EXPERIMENTAL_UMA_PREFIX) +
version_suffix + item.uma_name; HistogramProcessTypeToString(process_type) + version_suffix +
item.uma_name;
} }
if (item.is_large_metric) { if (item.is_large_metric) {
...@@ -329,7 +330,7 @@ void EmitProcessUma(const char* process_name, ...@@ -329,7 +330,7 @@ void EmitProcessUma(const char* process_name,
} }
void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd, void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd,
const char* process_name, HistogramProcessType process_type,
const base::Optional<base::TimeDelta>& uptime, const base::Optional<base::TimeDelta>& uptime,
bool record_uma, bool record_uma,
Memory_Experimental* builder) { Memory_Experimental* builder) {
...@@ -344,13 +345,13 @@ void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd, ...@@ -344,13 +345,13 @@ void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd,
break; break;
case EmitTo::kSizeInUmaOnly: case EmitTo::kSizeInUmaOnly:
if (record_uma) if (record_uma)
EmitProcessUma(process_name, item, value.value()); EmitProcessUma(process_type, item, value.value());
break; break;
case EmitTo::kSizeInUkmAndUma: case EmitTo::kSizeInUkmAndUma:
// For each 'size' metric, emit size as MB. // For each 'size' metric, emit size as MB.
EmitProcessUkm(item, value.value() / 1024 / 1024, builder); EmitProcessUkm(item, value.value() / 1024 / 1024, builder);
if (record_uma) if (record_uma)
EmitProcessUma(process_name, item, value.value()); EmitProcessUma(process_type, item, value.value());
break; break;
default: default:
NOTREACHED(); NOTREACHED();
...@@ -373,24 +374,24 @@ void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd, ...@@ -373,24 +374,24 @@ void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd,
if (!record_uma) if (!record_uma)
return; return;
const char* process_name = HistogramProcessTypeToString(process_type);
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
// Resident set is not populated on Mac. // Resident set is not populated on Mac.
DCHECK_EQ(pmd.os_dump().resident_set_kb, 0U); DCHECK_EQ(pmd.os_dump().resident_set_kb, 0U);
#else #else
MEMORY_METRICS_HISTOGRAM_MB( MEMORY_METRICS_HISTOGRAM_MB(
std::string(UMA_PREFIX) + process_name + ".ResidentSet", std::string(kMemoryHistogramPrefix) + process_name + ".ResidentSet",
pmd.os_dump().resident_set_kb / 1024); pmd.os_dump().resident_set_kb / 1024);
#endif #endif
MEMORY_METRICS_HISTOGRAM_MB( MEMORY_METRICS_HISTOGRAM_MB(GetPrivateFootprintHistogramName(process_type),
std::string(UMA_PREFIX) + process_name + ".PrivateMemoryFootprint", pmd.os_dump().private_footprint_kb / 1024);
pmd.os_dump().private_footprint_kb / 1024); MEMORY_METRICS_HISTOGRAM_MB(std::string(kMemoryHistogramPrefix) +
MEMORY_METRICS_HISTOGRAM_MB( process_name + ".SharedMemoryFootprint",
std::string(UMA_PREFIX) + process_name + ".SharedMemoryFootprint", pmd.os_dump().shared_footprint_kb / 1024);
pmd.os_dump().shared_footprint_kb / 1024);
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_LINUX) || defined(OS_ANDROID)
MEMORY_METRICS_HISTOGRAM_MB( MEMORY_METRICS_HISTOGRAM_MB(std::string(kMemoryHistogramPrefix) +
std::string(UMA_PREFIX) + process_name + ".PrivateSwapFootprint", process_name + ".PrivateSwapFootprint",
pmd.os_dump().private_footprint_swap_kb / 1024); pmd.os_dump().private_footprint_swap_kb / 1024);
#endif #endif
} }
...@@ -416,11 +417,11 @@ void EmitSummedGpuMemory(const GlobalMemoryDump::ProcessDump& pmd, ...@@ -416,11 +417,11 @@ void EmitSummedGpuMemory(const GlobalMemoryDump::ProcessDump& pmd,
pmd.GetMetric(gpu_categories[i], synthetic_metric.metric).value_or(0); pmd.GetMetric(gpu_categories[i], synthetic_metric.metric).value_or(0);
} }
// Always use "Gpu" as the process name for this even for the in process // Always use kGpu as the process name for this even for the in process
// command buffer case. // command buffer case.
EmitProcessUkm(synthetic_metric, total, builder); EmitProcessUkm(synthetic_metric, total, builder);
if (record_uma) if (record_uma)
EmitProcessUma("Gpu", synthetic_metric, total); EmitProcessUma(HistogramProcessType::kGpu, synthetic_metric, total);
} }
void EmitBrowserMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd, void EmitBrowserMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd,
...@@ -431,7 +432,8 @@ void EmitBrowserMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd, ...@@ -431,7 +432,8 @@ void EmitBrowserMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd,
Memory_Experimental builder(ukm_source_id); Memory_Experimental builder(ukm_source_id);
builder.SetProcessType(static_cast<int64_t>( builder.SetProcessType(static_cast<int64_t>(
memory_instrumentation::mojom::ProcessType::BROWSER)); memory_instrumentation::mojom::ProcessType::BROWSER));
EmitProcessUmaAndUkm(pmd, "Browser", uptime, record_uma, &builder); EmitProcessUmaAndUkm(pmd, HistogramProcessType::kBrowser, uptime, record_uma,
&builder);
EmitSummedGpuMemory(pmd, &builder, record_uma); EmitSummedGpuMemory(pmd, &builder, record_uma);
builder.Record(ukm_recorder); builder.Record(ukm_recorder);
...@@ -451,8 +453,10 @@ void EmitRendererMemoryMetrics( ...@@ -451,8 +453,10 @@ void EmitRendererMemoryMetrics(
memory_instrumentation::mojom::ProcessType::RENDERER)); memory_instrumentation::mojom::ProcessType::RENDERER));
builder.SetNumberOfExtensions(number_of_extensions); builder.SetNumberOfExtensions(number_of_extensions);
const char* process = number_of_extensions == 0 ? "Renderer" : "Extension"; const HistogramProcessType process_type =
EmitProcessUmaAndUkm(pmd, process, uptime, record_uma, &builder); (number_of_extensions == 0) ? HistogramProcessType::kRenderer
: HistogramProcessType::kExtension;
EmitProcessUmaAndUkm(pmd, process_type, uptime, record_uma, &builder);
if (page_info) { if (page_info) {
builder.SetIsVisible(page_info->is_visible); builder.SetIsVisible(page_info->is_visible);
...@@ -473,7 +477,8 @@ void EmitGpuMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd, ...@@ -473,7 +477,8 @@ void EmitGpuMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd,
Memory_Experimental builder(ukm_source_id); Memory_Experimental builder(ukm_source_id);
builder.SetProcessType( builder.SetProcessType(
static_cast<int64_t>(memory_instrumentation::mojom::ProcessType::GPU)); static_cast<int64_t>(memory_instrumentation::mojom::ProcessType::GPU));
EmitProcessUmaAndUkm(pmd, "Gpu", uptime, record_uma, &builder); EmitProcessUmaAndUkm(pmd, HistogramProcessType::kGpu, uptime, record_uma,
&builder);
EmitSummedGpuMemory(pmd, &builder, record_uma); EmitSummedGpuMemory(pmd, &builder, record_uma);
builder.Record(ukm_recorder); builder.Record(ukm_recorder);
} }
...@@ -486,7 +491,8 @@ void EmitUtilityMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd, ...@@ -486,7 +491,8 @@ void EmitUtilityMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd,
Memory_Experimental builder(ukm_source_id); Memory_Experimental builder(ukm_source_id);
builder.SetProcessType(static_cast<int64_t>( builder.SetProcessType(static_cast<int64_t>(
memory_instrumentation::mojom::ProcessType::UTILITY)); memory_instrumentation::mojom::ProcessType::UTILITY));
EmitProcessUmaAndUkm(pmd, "Utility", uptime, record_uma, &builder); EmitProcessUmaAndUkm(pmd, HistogramProcessType::kUtility, uptime, record_uma,
&builder);
builder.Record(ukm_recorder); builder.Record(ukm_recorder);
} }
...@@ -500,7 +506,8 @@ void EmitAudioServiceMemoryMetrics( ...@@ -500,7 +506,8 @@ void EmitAudioServiceMemoryMetrics(
Memory_Experimental builder(ukm_source_id); Memory_Experimental builder(ukm_source_id);
builder.SetProcessType(static_cast<int64_t>( builder.SetProcessType(static_cast<int64_t>(
memory_instrumentation::mojom::ProcessType::UTILITY)); memory_instrumentation::mojom::ProcessType::UTILITY));
EmitProcessUmaAndUkm(pmd, "AudioService", uptime, record_uma, &builder); EmitProcessUmaAndUkm(pmd, HistogramProcessType::kAudioService, uptime,
record_uma, &builder);
builder.Record(ukm_recorder); builder.Record(ukm_recorder);
} }
...@@ -514,7 +521,8 @@ void EmitNetworkServiceMemoryMetrics( ...@@ -514,7 +521,8 @@ void EmitNetworkServiceMemoryMetrics(
Memory_Experimental builder(ukm_source_id); Memory_Experimental builder(ukm_source_id);
builder.SetProcessType(static_cast<int64_t>( builder.SetProcessType(static_cast<int64_t>(
memory_instrumentation::mojom::ProcessType::UTILITY)); memory_instrumentation::mojom::ProcessType::UTILITY));
EmitProcessUmaAndUkm(pmd, "NetworkService", uptime, record_uma, &builder); EmitProcessUmaAndUkm(pmd, HistogramProcessType::kNetworkService, uptime,
record_uma, &builder);
builder.Record(ukm_recorder); builder.Record(ukm_recorder);
} }
......
...@@ -45,3 +45,14 @@ component("memory_instrumentation") { ...@@ -45,3 +45,14 @@ component("memory_instrumentation") {
"//services/service_manager/public/cpp", "//services/service_manager/public/cpp",
] ]
} }
source_set("browser") {
sources = [
"browser_metrics.cc",
"browser_metrics.h",
]
deps = [
"//base",
]
}
// Copyright 2019 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/public/cpp/memory_instrumentation/browser_metrics.h"
#include <cmath>
#include "base/rand_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
namespace memory_instrumentation {
namespace {
const char kAudioServiceHistogramName[] = "AudioService";
const char kBrowserHistogramName[] = "Browser";
const char kExtensionHistogramName[] = "Extension";
const char kGpuHistogramName[] = "Gpu";
const char kNetworkServiceHistogramName[] = "NetworkService";
const char kRendererHistogramName[] = "Renderer";
const char kUtilityHistogramName[] = "Utility";
} // namespace
const char kMemoryHistogramPrefix[] = "Memory.";
const char* HistogramProcessTypeToString(HistogramProcessType type) {
switch (type) {
case HistogramProcessType::kAudioService:
return kAudioServiceHistogramName;
case HistogramProcessType::kBrowser:
return kBrowserHistogramName;
case HistogramProcessType::kExtension:
return kExtensionHistogramName;
case HistogramProcessType::kGpu:
return kGpuHistogramName;
case HistogramProcessType::kNetworkService:
return kNetworkServiceHistogramName;
case HistogramProcessType::kRenderer:
return kRendererHistogramName;
case HistogramProcessType::kUtility:
return kUtilityHistogramName;
}
}
std::string GetPrivateFootprintHistogramName(HistogramProcessType type) {
return std::string(kMemoryHistogramPrefix) +
HistogramProcessTypeToString(type) + ".PrivateMemoryFootprint";
}
base::TimeDelta GetDelayForNextMemoryLog() {
#if defined(OS_ANDROID)
base::TimeDelta mean_time = base::TimeDelta::FromMinutes(5);
#else
base::TimeDelta mean_time = base::TimeDelta::FromMinutes(30);
#endif
// Compute the actual delay before sampling using a Poisson process.
double uniform = base::RandDouble();
return -std::log(uniform) * mean_time;
}
} // namespace memory_instrumentation
// Copyright 2019 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.
#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_BROWSER_METRICS_H_
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_BROWSER_METRICS_H_
#include <string>
#include "base/metrics/histogram_functions.h"
// Macro used for logging memory related metrics in mb.
#define MEMORY_METRICS_HISTOGRAM_MB(name, value) \
base::UmaHistogramCustomCounts(name, value, 1, 64000, 100)
namespace base {
class TimeDelta;
}
namespace memory_instrumentation {
// Prefix for memory related histograms.
extern const char kMemoryHistogramPrefix[];
// Types of processes uses by chrome.
enum class HistogramProcessType {
kAudioService,
kBrowser,
kExtension,
kGpu,
kNetworkService,
kRenderer,
kUtility,
};
// Returns a string used in histograms for the process of |type|.
const char* HistogramProcessTypeToString(HistogramProcessType type);
// Returns the memory footprint histogram name for the process of the specified
// type.
std::string GetPrivateFootprintHistogramName(HistogramProcessType type);
// Returns the delay used in logging memory related metrics.
base::TimeDelta GetDelayForNextMemoryLog();
} // namespace memory_instrumentation
#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_BROWSER_METRICS_H_
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