12

我想提高大型应用程序中特定方法的性能。

目标是改善延迟(在特定功能上花费的挂钟时间),而不是(必然)系统负载。

要求:

  1. 由于我预计很多延迟是由 I/O 引起的,请考虑等待/阻塞所花费的时间(换句话说:查看挂钟时间而不是 CPU 时间)
  2. 由于该程序比我要优化的片段做得更多。需要有一种方法可以以编程方式启动/停止分析,或者过滤输出以仅显示进入和退出我正在优化的函数之间的时间。
  3. 方法级别的分析是可以接受的(如果可以在指令级别完成,那就更好了。如果它只分析系统调用,那可能还不够)
  4. 这是一个爱好项目,所以昂贵的工具并不是一个真正的选择
  5. 仪器(-finstrument-functions)是可以接受的
  6. 我感兴趣的关键代码很难手动中断(因为它已经相对较快并且很难在循环中实际调用),因此某种自动化是必要的。

迄今为止丢弃的工具:

  • gprof、oprofile、callgrind(要求 1)
  • 使用 getrusage 构建自定义内容(要求 1)
  • Poormansprofiler.org(要求 2)
  • strace -T,dtrace,http ://perf.wiki.kernel.org (要求 2 和 3)
  • VTune,Zoom(要求 4)
  • 手动调用堆栈采样(要求 6)
  • google-perftools (应该能够测量挂墙时间,但这在我的情况下似乎不起作用,大概是因为 SIGALRM 干扰。
  • systemtap(我的内核没有打补丁以包含 utrace)

我尚未进一步评估的其他选项:

  • cprof (不是开箱即用的,似乎仅限 i386)
  • 手动插入跟踪点(例如使用 lttng)

我很想听听:

  • 其他选项
  • 也许我过早地丢弃了一些工具?
  • 我尚未评估的选项是否有机会发挥作用,如果有,如何最好地做到这一点。

我终于安顿下来了:

这个粗糙的工具产生的痕迹很难解释,我可以很容易地想象一些工具可以进一步处理它的输出,让它变得无限有用。但是,这暂时为我完成了这项工作,所以我将这个项目推迟到以后;)。

4

4 回答 4

3

使用这种方法

无论是在 CPU 还是 IO 绑定代码中,它在确定优化机会方面都非常简单有效。

如果您认为最大的机会在特定功能或模块中是正确的,那么它将找到它们。如果他们在别处,它会找到他们。

在您提到并丢弃的工具中,它与穷人的分析器最相似,但仍然不是很相似。

编辑:既然你说它是由用户交互触发并阻止进一步输入直到它完成,这就是我的做法。

首先,我假设它不会阻止到调试器的手动中断信号,因为否则您将无法停止无限循环。其次,我会在有问题的例程周围循环 10、100 或 1000 次,因此它执行的时间足够长,可以手动中断。

现在,假设它在 I/O 上花费了一小部分时间,比如 50%。然后当你中断它时,你有 50% 的机会在 I/O 中捕获它。因此,如果您在 I/O 中捕获它(调用堆栈会告诉您),您还可以非常详细地查看从哪里请求 I/O 以及请求的原因。

它会告诉你发生了什么,这几乎可以肯定是令人惊讶的。如果您看到它在少至两 (2) 个样本上做一些事情,您可以找到一种消除方法,那么您将获得相当大的加速。事实上,如果您消除该活动,您不会提前知道会节省多少时间,但平均而言,您可以期望节省分数F = (s+1)/(n+2),其中n是您采集的样本总数,s是显示活动的样本数。 继承规则 例如,如果您获取 4 个堆栈样本并查看其中 2 个的活动,平均而言,它将为您节省F = 3/6 = 1/2,对应于1/(1-F的加速因子)或 2。

完成此操作后,您可以再次执行此操作并找到其他要修复的内容。加速因素像复利一样相乘。

然后当然你移除外循环并“兑现”你得到的所有加速。

如果您想知道这与分析有何不同,那就是通过仔细检查每个堆栈样本以及可能的相关数据,您可以识别出您可以删除的活动,如果您所拥有的只是测量值,那么您只能尝试直觉到底是怎么回事。无论任何测量结果如何,您节省的实际时间都是如此。重要的是找到问题。无论分析器测量它的精度有多高,如果你找不到它,你就没有获胜。这些页面上到处都是人们说他们要么不明白他们的分析器告诉他们什么,要么似乎在说没有什么可以修复的,他们只是太愿意接受了。那是一副玫瑰色眼镜。

更多关于这一切。

于 2012-08-01T21:40:10.173 回答
3

对于 I/O 绑定应用程序,您可以使用--collect-systime=yescallgrind 选项。

这会收集系统调用所花费的时间(以毫秒为单位)。因此,如果您认为自己有 I/O 瓶颈,您可以使用这些统计数据来识别它。

于 2016-03-30T10:31:18.083 回答
1

Todo:检查“perf”(再次)

于 2016-07-18T12:40:26.783 回答
0
  • 叉()
  • execxxx(被测进程)
  • 在父母中:
    • (在循环中)定期调用:
    • getrusage(RUSAGE_CHILDREN, ...)

getrusage() 不仅会为您提供 cpu 使用率,还会为您提供主要/次要页面错误、上下文切换次数等。其余时间可能都花在等待 I/O 上。这不会为您提供详细的分析信息,而是提供程序行为的一个很好的整体足迹,与在每个进程的基础上运行 vmstat 相当。

于 2012-08-01T21:57:26.180 回答