socket编程项目性能优化之perf trace实践

在一个网络编程性能优化项目中,利用perf trace进行性能分析。
背景:一个进程负责处理socket消息,在需要处理消息数量达到32k条100+字节的消息量时,耗时大概需要25分钟
目标:定位耗时的热区
环境:linux

假设1:用户态耗时多,进程耗时多是消耗在算法计算上?

该进程只进行简单的消息处理,不涉及过多数据结构和算法,排除该可能性。

假设2:系统态耗时多,进程耗时多是消耗在系统调用上?

由于消息量大,进行了32k*n 数量级的系统调用,假设有可能成立。


在这里,选择使用linux的perf工具进行统计分析:
perf trace -p $PID -s

socket编程项目性能优化之perf trace实践_第1张图片

由上图可见,在处理一条消息的过程中,大致流程涉及到与socket相关的 poll->recvfrom->sendto,同时还有与文件IO相关的系统调用。处理32k条消息,涉及到的系统调用数量在数量级上符合预期。

  • 指标统计分析:
    fsync(), 该系统调用用时最多,消耗了大概15分钟。该系统调用用于同步写入磁盘,调用后会阻塞,直至等待内核缓冲区数据写入磁盘后,内核才会返回。定位到该系统调用位于进程的日志模块。
  • 针对该系统调用改善:
    业务数据日志,降低其日志等级,在运行进程时通过日志等级开发将对应的等级关闭,减少日志输出;同时在日志模块中删除fsync()调用,该类日志不需要实时同步至磁盘。

socket编程项目性能优化之perf trace实践_第2张图片

重新执行相同的测试,进程总用时大约50s。从本次检测到的系统调用指标来看,解决了fsync()带来了极大的提升空间。


在这个实践中,可以看到perf trace的一个用处:统计一定时间内的系统调用的次数以及其耗时分布。

思考1:perf trace统计的系统调用,各列中的时间是系统时间还是时钟时间?个人认为是时钟时间,因为尽管是系统调用,内核态也会处于一种阻塞状态,该状态不消耗CPU资源。例如进程调用fsync(),陷入内核态,DMA把系统缓冲区的数据同步至磁盘,此过程进程睡眠,没有占用CPU资源,同步至磁盘完成后,DMA会中断,CPU进行响应处理,此时fsync()调用结束,返回用户态。

你可能感兴趣的:(socket编程项目性能优化之perf trace实践)