【发布时间】:2011-05-01 09:00:45
【问题描述】:
我最近尝试使用 OProfile 分析我的应用程序。收集到的数据对我来说已经很有价值,但我很难准确解释。运行我的应用程序并设置并运行 oprofile 后,我生成了报告并得到:
root@se7xeon:src# opreport image:test -l -t 1
溢出统计信息不可用
CPU:P4 / Xeon,带 2 个超线程,速度 3191.66 MHz(估计)
计数 GLOBAL_POWER_EVENTS 事件(处理器未停止的时间),单位掩码为 0x01(强制)计数 750000
示例 % 符号名称
215522 84.9954 cci::Image::interpolate(unsigned char*, cci::Matrix const&) const
17998 7.0979 cci::Calc::diff(无符号字符常量*,无符号字符常量*)
13171 5.1942 cci::Image::getIRect(unsigned char*, int, int) 常量
5519 2.1765 cci::Image::getFRect(unsigned char*, double, double) const
好的,所以我的插值函数占应用程序(太长)执行时间的 84%。似乎是个好主意:
root@se7xeon:src# opannotate image:test --source
[...]
/* cci::Image::interpolate(unsigned char*, cci::Matrix<cci::Point2DF> const&) const total: 215522 84.9954 */
1392 0.5529 :void Image::interpolate(CCIPixel *output, const Matrix<Point2DF> &inputPoints) const throw()
4 0.0016 :{
[...]
: col0 = static_cast<int>(point[idx].x);
3 0.0012 : col1 = col0+1;
629 0.2498 : row0 = static_cast<int>(point[idx].y);
385 0.1529 : row1 = row0+1;
56214 22.3266 : if (col0 < 0 || col1 >= m_width || row0 < 0 || row1 >= m_height)
: {
: col0 = row0 = col1 = row1 = 0;
: }
如果我理解正确的话,if 条件占程序执行时间的 22% 以上。左大括号和函数声明似乎需要时间,这应该对应于函数调用开销(“入栈参数,跳转,弹出参数”序列)?
我更改了源代码中的一些内容(与后来的瓶颈有关,因为我不知道如何优化 if),重新编译,再次运行 oprofile(不要忘记 opcontrol --reset)。现在注释代码在同一个地方看起来像这样:
6 0.0024 : curPx = point[idx].x;
628 0.2477 : curPy = point[idx].y;
410 0.1617 : col0 = static_cast<int>(curPx);
57910 22.8380 : col1 = col0+1;
: row0 = static_cast<int>(curPy);
: row1 = row0+1;
: if (col0 < 0 || col1 >= m_width || row0 < 0 || row1 >= m_height)
: {
: col0 = row0 = col1 = row1 = 0;
: }
这一次 if 基本上不占用时间(?),最昂贵的指令是“col1 = col0 + 1”,整个耗时块似乎已经向上移动。怎么会这样?可以完全相信这可以查明源中的瓶颈吗?
我的另一个疑问是,当我设置 opcontrol 时,我将跟踪事件输入为 GLOBAL_POWER_EVENTS,样本数为 750k。在输出中,插值函数似乎占用了 84%,但其中记录的样本数仅略高于 200k。这甚至不是请求数量的 50%。我是否理解剩余的约 500k 样本是由未在输出中列出的应用程序(内核、Xorg 等)获取的?
【问题讨论】:
标签: c++ linux profiling oprofile