听说 Chromium 里有个直方图
2025-04-03
最近工作中经常使用 Chromium 里 Histogram 这个工具。
这是一个 Telemetry 机制,可用于统计、调试,甚至性能分析。
不可否认,Chromium 是一个广泛使用,且内部实现相当复杂的巨型工程项目。没有人能保证自己写的代码一定正确。
Bug 一定存在。
重要的不是假装它不存在,而是如何快速地识别、调试并解决(Identify, debug, and resolve)。
因此今天这篇文章,打算从 Histogram 的设计理念出发,探讨实现的方式,以及我们该如何理解可观测性(Observability)。
1. 设计理念
对于单用户问题,在不同平台上有着很多经典的工具。比如性能分析,Linux 有 Perf,Windows 有 Windows Performance Toolkit 等。
但对于群体问题,传统的工具便会失效。
怎么判断某个函数被调用的频次,某个关键操作的耗时分布如何,更常规的,DAU (Daily Active User,日活跃用户数)怎么统计。
Chromium Histogram 提供了一套跨平台、分布式的数据采集方案。
功能上的定位,有点类似前端领域的 Sentry🔗。
Histogram 的设计目标是:
- 高性能采样(无需锁)
- 支持多种数据类型(布尔、计数器、枚举、延迟等)
- 自动分桶和分位分析
- 精准的数据聚合和上传
2. 实现
Chromium Histogram 的关键部分有三个:
- 埋点
- 采样
- 上传
2.1 埋点
首先,Chromium 提供了多种类型的 Histogram,用于记录不同的数据类型。
类型 | 宏 | 描述 |
---|---|---|
Boolean | UMA_HISTOGRAM_BOOLEAN | 记录 true/false 的分布 |
Enumeration | UMA_HISTOGRAM_ENUMERATION | 记录枚举类型的取值情况 |
Custom Counts | UMA_HISTOGRAM_CUSTOM_COUNTS | 自定义区间和 bucket,用于记录计数(比如网络包大小) |
Times | UMA_HISTOGRAM_TIMES | 记录时间类型,支持微秒到秒 |
Sparse | UMA_HISTOGRAM_SPARSE_SLOWLY | 用于高稀疏度的整数数据统计 |
2.2 采样
Histogram 底层的数据存储,是一个多级桶(bucket)。
类似:
struct Histogram { std::string name; int min; int max; int bucket_count; std::vector<int> counts;};
不同的数据类型,分桶的策略也有所差异。这样可以降低存储开销,并提高采样分布的清晰度。
类型 | 桶布局 | 示例用途 |
---|---|---|
LinearHistogram | 等距 | 计数类事件 |
ExponentialHistogram | 对数 | 时间延迟、网络 RTT |
CustomHistogram | 手动指定 | 特殊值域分布(如视频帧率) |
Add()
的计数是原子的,线程安全且高效。
每个进程都有一个 HistogramBase
实例,并实现了延迟实例化(Lazy Initialization)。多进程埋点不冲突。
2.3 上传
Histogram 记录的数据不会实时上传。因为有一个采样缓存机制:
-
所有注册的 Histogram 都由
StatisticsRecorder
(只在 Browser 进程) 统一管理 -
触发上传时,所有 Histogram 数据被序列化(
HistogramSnapshotManager
) -
数据通过
UKM
、UMA
、或者 DevTools 的chrome://histograms
页面输出
跨进程的 Histogram 数据共享则是借助 PersistentMemoryAllocator
。
具体工作流程如下:
+-----------------+ +--------------------------+ | Renderer 进程 | | Browser 主进程 | |-----------------| |--------------------------| | Histogram::Add | | | | PersistentHistogram (写入共享内存) | | | ↓ | | | | PersistentMemoryAllocator | | | | | | +-----------------+ | | | StatisticsRecorder | | ↓ | | ImportGlobalPersistentHistograms()| | ↓ | | 合并数据并上传 UMA | +--------------------------+
3. 启发
对于开发者,使用 Histogram 打点是简单的。
正是由于它的简洁性和高性能,在尽可能减小对软件性能影响的同时,提高了开发者对于一个复杂系统内部运行过程的观测能力。
系统越透明,失控的可能性越小。
If you can not measure it, you can not improve it.
如果你不能衡量它,你就无法改进它。
4. 总结
我喜欢简单的东西。
无论是道理,还是 App。
简单本身便是一种强大。
好的道理,应该一两句话就能说清楚;好的 App,应该让不识字的儿童都能轻松上手。
当然,能化繁为简的人,往往有着对事物异于常人的洞察。
这是简单背后的不简单。
(完)
参考
- 本文作者:Plantree
- 本文链接:https://plantree.me/blog/2025/chromium-histogram/
- 版权声明:所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
最后更新于: 2025-04-11T06:47:04+08:00