Skip to content

Commit 53ccfa1

Browse files
Awallkyanonymous1-me
authored andcommitted
metrics: Enable font and glyph cache memory metrics in Cobalt (#9127)
This change enables the reporting of font-related memory usage metrics to UMA, which were previously defined in the engine but not collected. - Initialize the memory instrumentation client in the Cobalt browser process to enable process-level allocator dumps. - Update CobaltMetricsServiceClient to explicitly extract and record Skia (sk_glyph_cache) and Blink (font_caches/shape_caches) allocator dumps. - Add new font cache metrics to the memory histograms allowlist. - Add a new browsertest (font_metrics_browsertest) to verify that the new histograms are correctly populated on a running device. - Add documentation for the identified font metrics in cobalt/docs/. These metrics provide visibility into the memory footprint of character rasterization and text shaping caches, aiding in identifying font-related memory regressions and optimizing resource usage. Bug: 483758673 (cherry picked from commit 9769f6a)
1 parent f6bf31f commit 53ccfa1

File tree

9 files changed

+269
-18
lines changed

9 files changed

+269
-18
lines changed

cobalt/browser/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ source_set("browser") {
8080
"//components/os_crypt/sync",
8181
"//components/prefs",
8282
"//components/variations/service:service",
83+
"//services/resource_coordinator/public/cpp/memory_instrumentation",
8384
"//starboard:starboard_group",
8485
]
8586

cobalt/browser/cobalt_browser_main_parts.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,26 @@
1717
#include <memory>
1818

1919
#include "base/path_service.h"
20+
<<<<<<< HEAD
2021
#include "base/run_loop.h"
22+
=======
23+
#include "base/trace_event/memory_dump_manager.h"
24+
>>>>>>> 9769f6ae0c (metrics: Enable font and glyph cache memory metrics in Cobalt (#9127))
2125
#include "cobalt/browser/global_features.h"
2226
#include "cobalt/browser/metrics/cobalt_metrics_service_client.h"
2327
#include "cobalt/shell/browser/shell_paths.h"
2428
#include "components/metrics/metrics_service.h"
2529
#include "components/metrics_services_manager/metrics_services_manager.h"
2630
#include "content/public/browser/browser_context.h"
2731
#include "content/public/browser/browser_thread.h"
32+
<<<<<<< HEAD
2833
#include "content/public/browser/storage_partition.h"
2934
#include "services/network/public/mojom/cookie_manager.mojom.h"
35+
=======
36+
#include "content/public/browser/resource_coordinator_service.h"
37+
#include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
38+
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
39+
>>>>>>> 9769f6ae0c (metrics: Enable font and glyph cache memory metrics in Cobalt (#9127))
3040

3141
#if BUILDFLAG(IS_ANDROIDTV)
3242
#include "base/android/memory_pressure_listener_android.h"
@@ -41,11 +51,51 @@
4151

4252
namespace cobalt {
4353

54+
namespace {
55+
56+
void InitializeBrowserMemoryInstrumentationClient() {
57+
if (memory_instrumentation::MemoryInstrumentation::GetInstance()) {
58+
return;
59+
}
60+
61+
auto task_runner = base::trace_event::MemoryDumpManager::GetInstance()
62+
->GetDumpThreadTaskRunner();
63+
if (!task_runner->RunsTasksInCurrentSequence()) {
64+
task_runner->PostTask(
65+
FROM_HERE,
66+
base::BindOnce(&InitializeBrowserMemoryInstrumentationClient));
67+
return;
68+
}
69+
70+
if (memory_instrumentation::MemoryInstrumentation::GetInstance()) {
71+
return;
72+
}
73+
74+
// Register the browser process as a memory-instrumentation client.
75+
// This replicates content::InitializeBrowserMemoryInstrumentationClient()
76+
// while avoiding unauthorized header includes.
77+
mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator;
78+
mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess> process;
79+
auto process_receiver = process.InitWithNewPipeAndPassReceiver();
80+
content::GetMemoryInstrumentationRegistry()->RegisterClientProcess(
81+
coordinator.InitWithNewPipeAndPassReceiver(), std::move(process),
82+
memory_instrumentation::mojom::ProcessType::BROWSER,
83+
base::GetCurrentProcId(), /*service_name=*/std::nullopt);
84+
memory_instrumentation::ClientProcessImpl::CreateInstance(
85+
std::move(process_receiver), std::move(coordinator),
86+
/*is_browser_process=*/true);
87+
}
88+
89+
} // namespace
90+
4491
int CobaltBrowserMainParts::PreCreateThreads() {
4592
#if BUILDFLAG(IS_ANDROIDTV)
4693
starboard::android::shared::StarboardBridge::GetInstance()->SetStartupMilestone(17);
4794
#endif
4895
SetupMetrics();
96+
97+
InitializeBrowserMemoryInstrumentationClient();
98+
4999
#if BUILDFLAG(IS_ANDROIDTV)
50100
base::android::MemoryPressureListenerAndroid::Initialize(
51101
base::android::AttachCurrentThread());

cobalt/browser/metrics/cobalt_memory_metrics_emitter.cc

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,33 +64,33 @@ const CobaltMemoryMetricsEmitter::Metric kAllocatorDumpNamesForMetrics[] = {
6464
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
6565
{}},
6666
{"blink_objects/Document",
67-
"NumberOfDocuments",
67+
"Tiny.NumberOfDocuments",
6868
CobaltMemoryMetricsEmitter::MetricSize::kTiny,
6969
MemoryAllocatorDump::kNameObjectCount,
7070
CobaltMemoryMetricsEmitter::EmitTo::kCountsInUkmAndSizeInUma,
7171
{}},
7272
{"blink_objects/Frame",
73-
"NumberOfFrames",
73+
"Tiny.NumberOfFrames",
7474
CobaltMemoryMetricsEmitter::MetricSize::kTiny,
7575
MemoryAllocatorDump::kNameObjectCount,
7676
CobaltMemoryMetricsEmitter::EmitTo::kCountsInUkmAndSizeInUma,
7777
{}},
7878
{"blink_objects/LayoutObject",
79-
"NumberOfLayoutObjects",
79+
"Tiny.NumberOfLayoutObjects",
8080
CobaltMemoryMetricsEmitter::MetricSize::kTiny,
8181
MemoryAllocatorDump::kNameObjectCount,
8282
CobaltMemoryMetricsEmitter::EmitTo::kCountsInUkmAndSizeInUma,
8383
{}},
8484
{"blink_objects/Node",
85-
"NumberOfNodes",
85+
"Small.NumberOfNodes",
8686
CobaltMemoryMetricsEmitter::MetricSize::kSmall,
8787
MemoryAllocatorDump::kNameObjectCount,
8888
CobaltMemoryMetricsEmitter::EmitTo::kCountsInUkmAndSizeInUma,
8989
{}},
90-
{"font_caches",
91-
"FontCaches",
90+
{"font_caches/shape_caches",
91+
"Small.FontCaches",
9292
CobaltMemoryMetricsEmitter::MetricSize::kSmall,
93-
kEffectiveSize,
93+
"size",
9494
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
9595
{}},
9696
{"java_heap",
@@ -100,7 +100,7 @@ const CobaltMemoryMetricsEmitter::Metric kAllocatorDumpNamesForMetrics[] = {
100100
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
101101
{}},
102102
{"leveldatabase",
103-
"LevelDatabase",
103+
"Small.LevelDatabase",
104104
CobaltMemoryMetricsEmitter::MetricSize::kSmall,
105105
kEffectiveSize,
106106
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
@@ -135,14 +135,20 @@ const CobaltMemoryMetricsEmitter::Metric kAllocatorDumpNamesForMetrics[] = {
135135
kEffectiveSize,
136136
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
137137
{}},
138+
{"skia/sk_glyph_cache",
139+
"Skia.Small.SkGlyphCache",
140+
CobaltMemoryMetricsEmitter::MetricSize::kSmall,
141+
"size",
142+
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
143+
{}},
138144
{"sqlite",
139-
"Sqlite",
145+
"Small.Sqlite",
140146
CobaltMemoryMetricsEmitter::MetricSize::kSmall,
141147
kEffectiveSize,
142148
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
143149
{}},
144150
{"ui",
145-
"UI",
151+
"Small.UI",
146152
CobaltMemoryMetricsEmitter::MetricSize::kSmall,
147153
kEffectiveSize,
148154
CobaltMemoryMetricsEmitter::EmitTo::kSizeInUkmAndUma,
@@ -171,8 +177,8 @@ const CobaltMemoryMetricsEmitter::Metric kAllocatorDumpNamesForMetrics[] = {
171177

172178
constexpr char kExperimentalUmaPrefix[] = "Memory.Experimental.";
173179
constexpr char kVersionSuffixNormal[] = "2.";
174-
constexpr char kVersionSuffixSmall[] = "2.Small.";
175-
constexpr char kVersionSuffixTiny[] = "2.Tiny.";
180+
constexpr char kVersionSuffixSmall[] = "2.";
181+
constexpr char kVersionSuffixTiny[] = "2.";
176182

177183
static const char* MetricSizeToVersionSuffix(
178184
CobaltMemoryMetricsEmitter::MetricSize size) {

cobalt/browser/metrics/cobalt_metrics_browsertest.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ IN_PROC_BROWSER_TEST_F(CobaltMetricsBrowserTest,
108108
check_histogram("Memory.Experimental.Browser2.V8");
109109
check_histogram("Memory.Experimental.Browser2.V8.AllocatedObjects");
110110
check_histogram("Memory.Experimental.Browser2.Skia");
111+
check_histogram("Memory.Experimental.Browser2.Skia.Small.SkGlyphCache");
111112
check_histogram("Memory.Experimental.Browser2.Small.FontCaches");
112113
check_histogram("Memory.Experimental.Browser2.Small.LevelDatabase");
113114
check_histogram("Memory.Experimental.Browser2.Small.UI");

cobalt/browser/metrics/cobalt_metrics_service_client_test.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ class TestProcessMemoryMetricsEmitter : public CobaltMemoryMetricsEmitter {
8282
malloc_dump->numeric_entries["allocated_objects_size"] = 8 * 1024 * 1024;
8383
browser_dump->chrome_allocator_dumps["malloc"] = std::move(malloc_dump);
8484

85+
// Add Skia Glyph Cache dump
86+
auto skia_dump = memory_instrumentation::mojom::AllocatorMemDump::New();
87+
skia_dump->numeric_entries["size"] = 2 * 1024 * 1024;
88+
browser_dump->chrome_allocator_dumps["skia/sk_glyph_cache"] =
89+
std::move(skia_dump);
90+
91+
// Add Font Caches dump
92+
auto font_dump = memory_instrumentation::mojom::AllocatorMemDump::New();
93+
font_dump->numeric_entries["size"] = 512 * 1024;
94+
browser_dump->chrome_allocator_dumps["font_caches/shape_caches"] =
95+
std::move(font_dump);
96+
8597
dump_ptr->process_dumps.push_back(std::move(browser_dump));
8698

8799
auto global_dump =
@@ -366,6 +378,12 @@ TEST_F(CobaltMetricsServiceClientTest, RecordMemoryMetricsRecordsHistogram) {
366378
.GetAllSamples("Memory.Experimental.Browser2.Malloc.AllocatedObjects")
367379
.size(),
368380
1u);
381+
382+
// Experimental histograms (now with .Small. suffix in KB)
383+
histogram_tester.ExpectUniqueSample(
384+
"Memory.Experimental.Browser2.Skia.Small.SkGlyphCache", 2048, 1);
385+
histogram_tester.ExpectUniqueSample(
386+
"Memory.Experimental.Browser2.Small.FontCaches", 512, 1);
369387
}
370388

371389
TEST_F(CobaltMetricsServiceClientTest,
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2026 The Cobalt Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "base/run_loop.h"
16+
#include "base/test/metrics/histogram_tester.h"
17+
#include "base/threading/thread_restrictions.h"
18+
#include "cobalt/browser/global_features.h"
19+
#include "cobalt/browser/metrics/cobalt_metrics_service_client.h"
20+
#include "cobalt/browser/metrics/cobalt_metrics_services_manager_client.h"
21+
#include "cobalt/browser/switches.h"
22+
#include "cobalt/testing/browser_tests/browser/test_shell.h"
23+
#include "cobalt/testing/browser_tests/content_browser_test.h"
24+
#include "components/metrics/metrics_pref_names.h"
25+
#include "components/metrics_services_manager/metrics_services_manager.h"
26+
#include "components/prefs/pref_service.h"
27+
#include "content/public/test/browser_test.h"
28+
#include "content/public/test/browser_test_utils.h"
29+
#include "testing/gtest/include/gtest/gtest.h"
30+
31+
namespace cobalt {
32+
33+
class FontMetricsBrowserTest : public content::ContentBrowserTest {
34+
public:
35+
FontMetricsBrowserTest() = default;
36+
~FontMetricsBrowserTest() override = default;
37+
38+
void SetUpCommandLine(base::CommandLine* command_line) override {
39+
content::ContentBrowserTest::SetUpCommandLine(command_line);
40+
// Set a short interval for memory metrics to verify periodic recording.
41+
command_line->AppendSwitchASCII(switches::kMemoryMetricsInterval, "1");
42+
}
43+
};
44+
45+
IN_PROC_BROWSER_TEST_F(FontMetricsBrowserTest, RecordsFontHistograms) {
46+
base::HistogramTester histogram_tester;
47+
48+
base::ScopedAllowBlockingForTesting allow_blocking;
49+
auto* features = GlobalFeatures::GetInstance();
50+
51+
// Ensure metrics recording is started.
52+
features->metrics_services_manager()->UpdateUploadPermissions(true);
53+
54+
// Load a page with various characters to exercise font caches and fallback in
55+
// Blink.
56+
std::string html_content = R"(
57+
<html>
58+
<body>
59+
<p>Standard Latin text.</p>
60+
<p>Emoji: 😀 😃 😄 😁 😆 😅 😂 🤣 🦩 🦒 🦚 🦝</p>
61+
<p>Rare CJK: 𠜎 𠜱 𠝹 𠱓 𠱸 𠲖 𠳏 𠳕</p>
62+
</body>
63+
</html>
64+
)";
65+
66+
GURL url("data:text/html;charset=utf-8," + html_content);
67+
ASSERT_TRUE(content::NavigateToURL(shell()->web_contents(), url));
68+
69+
// Trigger a memory dump manually for testing.
70+
auto* manager_client = features->metrics_services_manager_client();
71+
ASSERT_TRUE(manager_client);
72+
auto* client = static_cast<CobaltMetricsServiceClient*>(
73+
manager_client->metrics_service_client());
74+
ASSERT_TRUE(client);
75+
76+
base::RunLoop run_loop;
77+
client->ScheduleRecordForTesting(run_loop.QuitClosure());
78+
run_loop.Run();
79+
80+
base::RunLoop().RunUntilIdle();
81+
82+
// Check for memory histograms (Skia Glyph Cache).
83+
EXPECT_GE(
84+
histogram_tester.GetAllSamples("Memory.Browser.PrivateMemoryFootprint")
85+
.size(),
86+
1u);
87+
88+
EXPECT_GE(
89+
histogram_tester
90+
.GetAllSamples("Memory.Experimental.Browser2.Skia.Small.SkGlyphCache")
91+
.size(),
92+
1u);
93+
94+
EXPECT_GE(histogram_tester
95+
.GetAllSamples("Memory.Experimental.Browser2.Small.FontCaches")
96+
.size(),
97+
1u);
98+
}
99+
100+
} // namespace cobalt

cobalt/docs/font_metrics.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Font Resource and Memory Usage Metrics in Cobalt
2+
3+
This document summarizes the UMA histograms, Memory Infra dumps, and performance metrics used to track font, glyph cache, and text rendering resource usage in Cobalt.
4+
5+
## 1. Memory Consumption (Memory Infra / UMA)
6+
7+
These metrics track actual bytes used in RAM and GPU memory.
8+
9+
### Skia Graphics Layer
10+
* **Skia Glyph Cache**
11+
* **Dump Path**: `skia/sk_glyph_cache`
12+
* **UMA Mapping**: `Memory.Experimental.[Process].Skia.SkGlyphCache`
13+
* **Description**: Tracks the memory used by Skia's internal "Strike" cache (rasterized glyph masks).
14+
* **Source**: `skia/ext/skia_memory_dump_provider.cc` via `SkGraphics::GetFontCacheUsed()`.
15+
* **Cobalt Status**: Enabled in `cobalt/tools/uma/memory_histograms.txt`.
16+
17+
* **GPU Glyph Atlas**
18+
* **Dump Path**: `skia/gpu_resources/glyph_atlas` (in Chromium/Skia)
19+
* **UMA Mapping**: `Memory.Gpu.Skia.GpuResources.GlyphAtlas`
20+
* **Description**: Memory used by the GPU texture atlas where glyphs are packed for hardware-accelerated rendering.
21+
22+
### Blink / Renderer Layer
23+
* **Font Shape Caches**
24+
* **Dump Path**: `font_caches/shape_caches`
25+
* **UMA Mapping**: `Memory.Experimental.[Process].FontCaches`
26+
* **Description**: Memory used for caching text shaping results (the output of HarfBuzz).
27+
* **Source**: `third_party/blink/renderer/platform/fonts/font_cache.cc`.
28+
29+
* **Font Platform Data Cache**
30+
* **Dump Path**: `font_caches/font_platform_data_cache`
31+
* **Description**: Tracks memory used by the cache of platform-specific font handles.
32+
* **Allowlist**: Included in `base/trace_event/memory_infra_background_allowlist.cc`.
33+
34+
## 2. Resource Efficiency & Cache Performance
35+
36+
* **RenderTextHarfBuzz.ShapeRunsFallback**
37+
* **Type**: Enumeration
38+
* **Description**: Tracks how often font fallback is triggered during the text shaping phase.
39+
* **Source**: `ui/gfx/render_text_harfbuzz.cc`.
40+
41+
* **RenderTextHarfBuzz.GetFallbackFontTime**
42+
* **Type**: Times (ms)
43+
* **Description**: Time spent searching for a suitable fallback font when a character is missing.
44+
* **Source**: `ui/gfx/render_text_harfbuzz.cc`.
45+
46+
* **Blink.Fonts.DecodeTime**
47+
* **Type**: Microseconds
48+
* **Description**: Time spent decoding font resources.
49+
* **Source**: `third_party/blink/renderer/platform/fonts/font_resource.cc`.
50+
51+
## 3. Cobalt Integration Details
52+
53+
* **Metrics Management**: `cobalt/browser/metrics/cobalt_metrics_service_client.cc` coordinates global memory dumps.
54+
* **Allowlist**: Cobalt-specific histogram reporting is controlled by `cobalt/tools/uma/memory_histograms.txt`.
55+
56+
## How to Verify in Cobalt
57+
58+
1. **Memory Dumps**: Trigger a global memory dump via CDP or the internal metrics service to see the `skia/sk_glyph_cache` and `font_caches/*` breakdown.
59+
2. **UMA Verification**: Use `cobalt/tools/uma/pull_uma_histogram_set_via_cdp.py` to fetch currently recorded histograms from a running Cobalt instance and verify font-related entries.
60+
3. **Unit Tests**: Exercise `ui/gfx/render_text_unittest.cc` or similar tests to see histogram emission in a controlled environment.

cobalt/testing/browser_tests/BUILD.gn

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,18 @@ test("cobalt_browsertests") {
195195

196196
sources = [
197197
"//cobalt/browser/metrics/cobalt_metrics_browsertest.cc",
198+
<<<<<<< HEAD
199+
=======
200+
"//cobalt/browser/metrics/font_metrics_browsertest.cc",
201+
"content_main_runner_impl_browsertest.cc",
202+
203+
#"encrypted_media_browsertest.cc",
204+
#"frame_tree_browsertest.cc",
205+
#"media_browsertest.cc",
206+
#"media_browsertest.h",
207+
#"media_session_browsertest.cc",
208+
#"media_source_browsertest.cc",
209+
>>>>>>> 9769f6ae0c (metrics: Enable font and glyph cache memory metrics in Cobalt (#9127))
198210
"//cobalt/shell/browser/h5vcc_scheme_url_loader_factory_browsertest.cc",
199211
"content_main_runner_impl_browsertest.cc",
200212
"encrypted_media_browsertest.cc",

0 commit comments

Comments
 (0)