Histogram是base库的统计功能,用于方便、高效地址代码里面插入一些统计打点。统计结果既可以由程序自发地在VLOG打开的情况下打印出来,也可以自己决定要输出哪些统计项目。
统计结果主要包含了统计个数、总和、每个打点的落点分布,这些信息可以用多种方式展示,例如ASCII文本、HTML、JSON。
文本方式的输出结果可以打开chrome,输入 chrome://histograms/ 看到。
要用这个功能很简单,只需要在模块代码的入口处加上 base::StatisticsRecorder::Initialize();
即可。如果需要让程序退出时能够自动打印出统计结果,则这行代码需要放在日志的初始化以后,以便统计模块初始化时能够正确判断出VLOG有没有打开,从而把程序退出时写日志的函数注册到AtExitManager里。
用的地方更加简单,包含头文件base/metrics/histogram_macros.h
,这个文件wrap了供外部使用的常用统计宏,如果不够,可以在自己的代码里再类似地加个这样的文件。
在这些宏定义里,STATIC_HISTOGRAM_POINTER_BLOCK
是最终的实现,不需要直接使用。由它衍生而来的有2类:LOCAL 开头和 UMA 开头的定义,区别在于 LOCAL_ 开头的定义中,flag是统一设成kNoFlags
,而UMA是一种可以把统计信息通过IPC消息实时地发送给UMA HOST的机制,它的实现类似于MFC的消息处理,以下是一段示例:
int32_t PepperFlashBrowserHost::OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) {
PPAPI_BEGIN_MESSAGE_MAP(PepperFlashBrowserHost, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Flash_UpdateActivity,
OnUpdateActivity)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Flash_GetLocalTimeZoneOffset,
OnGetLocalTimeZoneOffset)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
PpapiHostMsg_Flash_GetLocalDataRestrictions, OnGetLocalDataRestrictions)
PPAPI_END_MESSAGE_MAP()
return PP_ERROR_FAILED;
}
由于还没有场景要用到,没有细看。
LOCAL_系列的宏定义常用的有如下几种:LOCAL_HISTOGRAM_CUSTOM_COUNTS
、 LOCAL_HISTOGRAM_CUSTOM_TIMES
(以及衍生出来的几个) 、LOCAL_HISTOGRAM_BOOLEAN
、 LOCAL_HISTOGRAM_ENUMERATION
等,以 LOCAL_HISTOGRAM_CUSTOM_COUNTS 为例来说明,它的定义如下:
#define LOCAL_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
base::Histogram::FactoryGet(name, min, max, bucket_count, \
base::HistogramBase::kNoFlags))
最后是一个简单用法示例:
LOCAL_HISTOGRAM_BOOLEAN("X509CertificateReuseCount", true);
以chrome里的时间类型的统计项为例说明如何读它的输出结果( 在代码里可以用base::StatisticsRecorder::StatisticsRecorder::WriteGraph("item_name")
来得到 ):
Histogram: DiskCache.2.TotalIOTime recorded 29 samples, mean = 5.3 (flags = 0x1)
0 ------------------------------------------------------------------------O (20 = 69.0%)
1 ...
8 --O (1 = 3.4%) {69.0%}
10 --O (1 = 3.4%) {72.4%}
12 ----O (2 = 6.9%) {75.9%}
14 -O (1 = 3.4%) {82.8%}
17 ----O (3 = 10.3%) {86.2%}
20 ...
40 -O (1 = 3.4%) {96.6%}
48 ...
这里表示一共有29个样本,平均值5.3,其中有20个样本落在了0--1的区间,2个值为12的样本,占比6.9%,此时之前的样本累计占比75.9%.
例如监测每个任务执行以后的内存占用情况:LOCAL_HISTOGRAM_MEMORY_KB(name, sample)
// For measuring memory usage after each task. Behind a command line flag.
class MemoryObserver : public base::MessageLoop::TaskObserver {
...
void DidProcessTask(const base::PendingTask& pending_task) override {
LOCAL_HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB());
}
...
};
对于网络、数据库等情况, VS的分析工具并不能或不能精确地分析耗时,例如mail_operation里的网络请求。
用到的宏:LOCAL_HISTOGRAM_TIMES(name, sample)
例如探测字符集的情况,可以直接用ICU获得所有可能的字符集,也可以先快速地先对我们优先考虑的字符集探测一遍(顺序为UTF-8 --> GBK --> BIG5 ),如果失败再用ICU。 这种方法对小字符串的探测性能和准确度提升明显,通过统计,使用这个函数判断的95%以上都是256字节以内,因此取阈值256.
用到的宏:LOCAL_HISTOGRAM_COUNTS_10000(name, sample)
Histogram: SmartConvertString_Size recorded 939 samples, average = 58.3
0 O (0 = 0.0%)
1 ------------------------------O (41 = 4.4%) {0.0%}
2 --------------------------------------------------O (69 = 7.3%) {4.4%}
3 ---------------------------------------------------------O (78 = 8.3%) {11.7%}
4 ------------------------------------------------------------------------O (99 = 10.5%) {20.0%}
5 --------O (11 = 1.2%) {30.6%}
6 ------------O (16 = 1.7%) {31.7%}
7 --O (3 = 0.3%) {33.4%}
8 -------O (20 = 2.1%) {33.8%}
10 -----O (14 = 1.5%) {35.9%}
12 ---------------O (41 = 4.4%) {37.4%}
14 -------------O (52 = 5.5%) {41.7%}
17 ------O (26 = 2.8%) {47.3%}
20 ----------O (56 = 6.0%) {50.1%}
24 ----------O (66 = 7.0%) {56.0%}
29 ------------O (80 = 8.5%) {63.0%}
34 --O (14 = 1.5%) {71.6%}
40 ------O (41 = 4.4%) {73.1%}
48 O (3 = 0.3%) {77.4%}
57 -O (6 = 0.6%) {77.7%}
68 ----O (28 = 3.0%) {78.4%}
81 O (0 = 0.0%) {81.4%}
96 --------O (54 = 5.8%) {81.4%}
114 ---O (23 = 2.4%) {87.1%}
135 O (0 = 0.0%) {89.6%}
160 -------O (50 = 5.3%) {89.6%}
190 O (0 = 0.0%) {94.9%}
226 O (3 = 0.3%) {94.9%}
268 -O (5 = 0.5%) {95.2%}
318 ---O (20 = 2.1%) {95.7%}
378 -O (8 = 0.9%) {97.9%}
449 ...
633 -O (7 = 0.7%) {98.7%}
752 O (0 = 0.0%) {99.5%}
894 O (1 = 0.1%) {99.5%}
1062 O (1 = 0.1%) {99.6%}
1262 O (0 = 0.0%) {99.7%}
1500 O (3 = 0.3%) {99.7%}
1782 ...
例如字符串的编码自动判断的成功和失败的个数 / 收发信频繁出现网络错误 / 日历同步失败率
用到的宏:LOCAL_HISTOGRAM_BOOLEAN
例如用户习惯统计(例如邮箱大师从哪里启动,发送邮件时是用快捷键还是点按钮,输入邮箱帐号时输了多少字才利用了我们的自动完成功能等)
用到的宏:LOCAL_HISTOGRAM_ENUMERATION(name, sample, boundary_value)
本文来自网易实践者社区,经作者郁利涛授权发布。