windbg常见问题--分析CPU高

项目场景:

某天工作时在运维群中收到服务器告警提示cpu基本满负荷了,这个服务已经都运行了快3个月了。

信息收集

对于cpu高问题,先在现场环境观察排除一些外在因素,

  • 程序的内存是否正常,比如有内存泄漏,物理内存不足导致高的换页操作
  • 比如文件IO是否正常,比如有异常的copy操作、硬盘坏道
  • 观察网络流量是否正常
  • 观察下任务管理器,是否有cpu过高的进程,比如后台杀毒
  • 通过processxp查看进行哪些线程cpu占用率高;通过导入pdb文件,也可查看是哪个函数耗时

对于生产环境高cpu的问题,我比较喜欢多采样的方式,通过分析多个时间点的dump找到线程执行的相识处,找到cpu耗时的函数。因此在短时间内我保存了大概10个dump,剩下的就是分析他们的共同点,找到耗cpu的函数。

原因分析:

dump下载,提取码q5kx

切换为x86模式

0:000> .load wow64exts
0:000> !sw
Switched to 32bit mode
0:000:x86> ~*kv

windbg打开dump文件,并设置好pdb文件,查看每个线程的执行时间

> ~*e?@$tid;.ttime
.......
Created: Wed Sep 20 06:03:24.274 2017 (UTC + 8:00)
Kernel:  0 days 0:00:56.187
User:    0 days 0:00:48.468
Evaluate expression: 3756 = 00000eac
Created: Wed Sep 20 06:03:24.274 2017 (UTC + 8:00)
Kernel:  0 days 1:50:47.906
User:    5 days 10:32:08.953
Evaluate expression: 1924 = 00000784
Created: Wed Sep 20 06:03:24.274 2017 (UTC + 8:00)
Kernel:  0 days 2:09:43.734
User:    5 days 18:12:02.671
Evaluate expression: 4964 = 00001364
Created: Wed Sep 20 06:03:24.274 2017 (UTC + 8:00)
Kernel:  0 days 1:50:15.734
User:    5 days 13:41:16.296
Evaluate expression: 2080 = 00000820
Created: Wed Sep 20 06:03:24.274 2017 (UTC + 8:00)
Kernel:  0 days 1:49:48.000
User:    5 days 11:29:27.156
Evaluate expression: 3456 = 00000d80
Created: Wed Sep 20 06:03:24.274 2017 (UTC + 8:00)
Kernel:  0 days 1:50:28.812
User:    5 days 10:26:11.093
Evaluate expression: 3632 = 00000e30
Created: Wed Sep 20 06:03:24.274 2017 (UTC + 8:00)
Kernel:  0 days 2:10:05.953
User:    5 days 18:17:44.187
Evaluate expression: 1216 = 000004c0
Created: Wed Sep 20 06:03:24.290 2017 (UTC + 8:00)
Kernel:  0 days 1:50:44.031
User:    5 days 13:33:37.000
Evaluate expression: 728 = 000002d8
Created: Wed Sep 20 06:03:24.290 2017 (UTC + 8:00)
Kernel:  0 days 1:49:10.500
User:    5 days 11:18:50.250
Evaluate expression: 3424 = 00000d60
Created: Wed Sep 20 06:03:24.290 2017 (UTC + 8:00)
Kernel:  0 days 1:24:44.234
User:    0 days 2:01:17.203
Evaluate expression: 2944 = 00000b80
................

可以找到有8个线程耗时比较多

进程使用的是消费者模型,总共有8个线程用于处理请求消息,因此这8个线程是高耗时的线程

对比多个dump的共同点

这里省略了其他dump,最终比对的结果,就是几乎每个dump都有一个线程在执行“CSockServer::OnPlayerLogon” 函数。
因此我们查看下OnPlayerLogon的详细信息,切换到9号线程,
> ~9s

在这里插入图片描述
通过查看 local 信息查看变量的值:
windbg常见问题--分析CPU高_第1张图片
可以看到这个CMap的数量是70w左右。使用的是MFC的CMap难道SetAt性能不好? 由于是前人的历史代码,我对CMap基本不熟悉,所以就抱着这个疑问写了个demo进行验证,果然,在CMap达到40w左右时,SetAt性能急剧下降,到70w左右插入可能需要10秒的时间。

解决方案:

将CMap更换了std::map ,性能稳定。

总结

高CPU的问题,我没有特别好的解决方案,特别是在生产环境中长时间运行,一般还是通过观察和多采样进行分析,需要具体情况具体分析,有的问题可能通过查看线程耗时就能找到某个耗时的线程,有的情况就需要进行更加复杂的操作。

last

对于dump分析也可以留言,进行协助分析。

你可能感兴趣的:(软件调试,c++,运维,windbg)