我尝试运行 Kinopiko 的示例,但我将迭代次数增加了 100 倍。
test.c:
#include <stdio.h>
int main ()
{
int i;
for (i = 0; i < 1000000; i++) {
printf ("%d\n", i);
}
return 0;
}
然后我取了10个stackshots(在VC下,不过可以用pstack)。以下是堆栈截图:
9 copies of this stack:
NTDLL! 7c90e514()
KERNEL32! 7c81cbfe()
KERNEL32! 7c81cc75()
KERNEL32! 7c81cc89()
_write() line 168 + 57 bytes
_flush() line 162 + 23 bytes
_ftbuf() line 171 + 9 bytes
printf() line 62 + 14 bytes
main() line 7 + 14 bytes
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817077()
1 copy of this stack:
KERNEL32! 7c81cb96()
KERNEL32! 7c81cc75()
KERNEL32! 7c81cc89()
_write() line 168 + 57 bytes
_flush() line 162 + 23 bytes
_ftbuf() line 171 + 9 bytes
printf() line 62 + 14 bytes
main() line 7 + 14 bytes
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817077()
如果不是很明显,这会告诉您:
mainCRTStartup() line 206 + 25 bytes Cost ~100% of the time
main() line 7 + 14 bytes Cost ~100% of the time
printf() line 62 + 14 bytes Cost ~100% of the time
_ftbuf() line 171 + 9 bytes Cost ~100% of the time
_flush() line 162 + 23 bytes Cost ~100% of the time
_write() line 168 + 57 bytes Cost ~100% of the time
简而言之,作为第 7 行的 printf 的一部分,程序花费了大约 100% 的时间将输出缓冲区刷新到磁盘(或控制台)。
(我所说的“线路成本”的意思是 - 它是应该线路的请求所花费的总时间的一部分,这大致是包含它的样本的一部分。
如果可以使该行不占用任何时间,例如通过删除它、跳过它或将其工作传递给一个无限快的协处理器,那么该时间分数就是总时间将减少多少。因此,如果可以避免执行任何这些代码行,时间将缩短 95% 到 100%。如果您要问“递归呢?”,答案是 It Makes No Difference.)
现在,也许您想知道其他信息,例如在循环中花费了多少时间。要找出答案,请删除 printf,因为它一直在占用。也许您想知道有多少时间纯粹花在 CPU 时间上,而不是花在系统调用上。要做到这一点,只需丢弃所有未在您的代码中结束的堆栈快照。
我想说的是,如果您正在寻找可以修复的东西以使代码运行得更快,那么即使您理解,gprof 为您提供的数据也差不多无用。相比之下,如果您的某些代码导致花费的挂钟时间超出您的预期,则堆栈快照会查明它。