strace -c 统计系统调用耗时
更新时间:2026-09-18。当
%system(内核态)CPU 偏高时,strace -c用一张汇总表告诉你时间花在哪些系统调用上。基础用法见 strace 系统调用,火焰图级定位见 perf 实战。
这个工具是做什么的
strace 基于 ptrace 拦截每次系统调用;-c 不打印逐条明细,而是在结束(Ctrl-C / 进程退出)时输出按调用聚合的统计:次数、累计耗时、单次均时、错误数。适合回答「内核态时间到底烧在哪个 syscall 上」。
bash
strace -c -p <PID> # 附加运行中的进程,跑几秒后 Ctrl-C 出汇总
strace -f -c ./myapp # -f 同时跟踪所有子线程/子进程
strace -c -e trace=network ./server # 只统计网络相关 syscall输出怎么读
bash
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
45.20 0.031200 15 2080 futex
30.10 0.020800 42 490 epoll_wait
15.00 0.010300 3 3400 120 read
9.70 0.006700 10 670 write- calls 异常多:如
read/write数万次,常是小块频繁 IO / 没缓冲 / Nagle 交互。 - errors 列:大量
EAGAIN(非阻塞 IO 正常重试)、ECONNRESET、ENOENT(反复 stat 不存在的文件)往往暴露逻辑问题。 - usecs/call 很大:单次慢,如
fsync、connect、磁盘读,指向 IO/网络延迟而非次数。
典型对症
| 现象(Top syscall) | 方向 |
|---|---|
futex 占比极高 | 锁竞争/大量线程同步,配合 jstack 看 BLOCKED |
epoll_wait/kevent 多但不慢 | 正常事件循环空转,未必是问题 |
openat/stat 海量 + ENOENT | 反复查找文件/类路径/配置,缺缓存 |
write/sendto 次数巨大 | 小包写入,考虑批量/缓冲、TCP_NODELAY 取舍 |
fsync/fdatasync 慢 | 刷盘瓶颈,关注磁盘与持久化策略 |
常见坑
- 开销极大:ptrace 每次 syscall 两次上下文切换,目标会被拖慢数倍~数十倍,只短时采样几秒,绝不在生产热路径长挂。
- 忘了
-f:多线程服务只跟踪主线程会漏掉真正干活的工作线程,数据严重失真。 % time受调度影响:某些 syscall 的秒数含阻塞等待时间(如epoll_wait、futex睡眠),高占比不一定是烧 CPU,要结合 calls/usecs 解读。- 高频场景用错工具:持续观测低开销应选
perf trace或 eBPF(bpftrace/bcc的funclatency),strace 适合即时、短时定性。 - 只看总量不下钻:
-c给方向后,用strace -T -e trace=<syscall> -p PID看单次明细与参数确认。
总结
strace -c 在内核态 CPU 偏高时用 ptrace 聚合一页系统调用统计,靠 calls 次数、errors 错误数和 usecs/call 单次耗时定位高频或慢的 syscall:futex 多指锁竞争、海量 read/write 指频繁小 IO、大量 ENOENT 指反复 stat 缺失文件、fsync 慢指刷盘瓶颈;但 ptrace 开销巨大只能短时采样且多线程必须加 -f,同时要注意 epoll_wait/futex 的高时间占比可能只是阻塞睡眠而非烧 CPU,持续低开销观测应改用 perf trace 或 eBPF,再用带 -T 的明细模式下钻确认。