如何降低lsphp进程中getppid()的执行耗时?
高CPU占用排查:lsphp进程中getppid()耗时超1秒的优化方案
我正在排查高CPU占用问题,在追踪某一lsphp进程时发现,getppid()系统调用每次执行耗时均超过1秒。以下是strace追踪日志:
strace: Process 21945 attached 0.000000 select(5, 0x7fffadebf9e0, NULL, NULL, 0x7fffadebf9d0) = 0 (Timeout) 0.992306 getppid() = 31441 0.000169 select(5, 0x7fffadebf9e0, NULL, NULL, 0x7fffadebf9d0) = 1 (in [4], left 0x7fffadebf9d0) 0.714351 accept(4, 0x7fffadebf920, 0x7fffadebf91c) = -1 EAGAIN (Resource temporarily unavailable) 0.000121 select(5, 0x7fffadebf9e0, NULL, NULL, 0x7fffadebf9d0) = 0 (Timeout) 1.000415 getppid() = 31441 0.000030 select(5, 0x7fffadebf9e0, NULL, NULL, 0x7fffadebf9d0) = 0 (Timeout) 1.001052 getppid() = 31441 0.000030 select(5, 0x7fffadebf9e0, NULL, NULL, 0x7fffadebf9d0) = 0 (Timeout) 1.000785 getppid() = 31441 0.000083 select(5, 0x7fffadebf9e0, NULL, NULL, 0x7fffadebf9d0) = 0 (Timeout) 1.000875 getppid() = 31441 0.000038 select(5, 0x7fffadebf9e0, NULL, NULL, 0x7fffadebf9d0) = 0 (Timeout)
优化方法
定位父进程异常
getppid()本身是轻量系统调用,正常耗时在微秒级。耗时超1秒几乎可以确定是父进程(PID 31441)无法被内核正常调度:- 用
ps aux | grep 31441查看父进程状态,如果是D状态,说明它卡在IO等待(比如磁盘故障、NFS挂载无响应) - 用
strace -p 31441追踪父进程的系统调用,确认是否卡在某个阻塞操作上 - 检查父进程是否被高优先级进程抢占,导致长期无法获得CPU时间片
- 用
减少getppid()调用次数
如果业务代码中频繁调用getppid(),可以通过缓存优化:- 进程启动时一次性获取父进程ID并保存到内存变量,后续直接使用变量,避免重复发起系统调用
- 若父进程存在意外重启的可能,可设置定时刷新逻辑(比如每30秒重新获取一次),而非每次操作都调用
排查系统层面瓶颈
- 用
top、vmstat检查系统整体负载,确认CPU、内存、IO是否有资源耗尽的情况 - 检查内核参数:比如
kernel.pid_max如果设置过小,会导致进程列表遍历缓慢;sysctl kernel.sched_rt_runtime_us等调度参数是否异常 - 用
iostat、dmesg排查磁盘性能,若父进程依赖磁盘IO,磁盘卡顿会间接导致getppid()调用阻塞
- 用
内容的提问来源于stack exchange,提问作者Phuc Pham
相关产品推荐
相关产品推荐

