软件调试系列:高CPU排查方法浅谈

软件性能较差,占用CPU较多,往往是由于某段代码逻辑算法不佳导致,那如何在数以千计的函数中找到问题函数呢?

这类问题的排查有很多方法,这里介绍如何用神器Windbg是排查。

其中,排查步骤如下

步聚1:在使用!runaway命令比较不同时间各线程占用CPU时间,找到CPU时间增涨较多的线程,那么就初步定位了问题函数所在的问题线程,

步聚2:然后在不同的时刻观察问题线程的调用栈,如果多次观察到截取的调用栈在执行某个函数,那么就有理由相信该函数调用存在性能问题。

步聚3:修改代码指令,屏敝对问题函数的调用,观察CPU占用率是否有明显下降,若是,则说明第2步骤找到的问题函数存在性能瓶颈,需进一步优化。

现在来实战一下,现在有一进程testpid=3032)占用CPU 30,如下图所示,现在按前面所述的步聚执行;

步聚一:使用!runaway命令比较不同时间各线程占用CPU时间

0:002> !runaway

 User Mode Time

  Thread       Time

   1:d9c       0 days 0:04:10.506

   0:be8       0 days 0:00:00.046

   2:a34       0 days 0:00:00.000

0:002> g

(ad8.9e4): Break instruction exception - code 80000003 (first chance)

eax=7ffdd000 ebx=00000000 ecx=00000000 edx=77f5d5cb esi=00000000 edi=00000000

eip=77ef3258 esp=0290ff5c ebp=0290ff88 iopl=0         nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

77ef3258 cc              int     3

0:002> !runaway

 User Mode Time

  Thread       Time

   1:d9c       0 days 0:04:12.690

   0:be8       0 days 0:00:00.046

   2:9e4       0 days 0:00:00.000

0:002> g

(ad8.f8c): Break instruction exception - code 80000003 (first chance)

eax=7ffdd000 ebx=00000000 ecx=00000000 edx=77f5d5cb esi=00000000 edi=00000000

eip=77ef3258 esp=0290ff5c ebp=0290ff88 iopl=0         nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

77ef3258 cc              int     3

0:002> !runaway

 User Mode Time

  Thread       Time

   1:d9c       0 days 0:04:15.420

   0:be8       0 days 0:00:00.046

   2:f8c       0 days 0:00:00.000

以上三次执行!runaway命令时间间隔在几秒左右,发现1号线程占用cpu时间相比其它线程有较大的增涨。

步聚2:多次观察到截取的调用栈情况,是否在多次执行某个函数

0:001> k

ChildEBP RetAddr  

0280ff28 00401d33 test!d+0x3c [E:\test\test\testDlg.cpp @ 183]

0280ff88 77e31154 test!Test+0x33 [E:\test\test\testDlg.cpp @ 194]

WARNING: Stack unwind information not available. Following frames may be wrong.

0280ff94 77f1b299 kernel32!BaseThreadInitThunk+0x12

0280ffd4 77f1b26c ntdll!__RtlUserThreadStart+0x70

0280ffec 00000000 ntdll!_RtlUserThreadStart+0x1b

0:001> g

(ad8.a80): Break instruction exception - code 80000003 (first chance)

eax=7ffdd000 ebx=00000000 ecx=00000000 edx=77f5d5cb esi=00000000 edi=00000000

eip=77ef3258 esp=0290ff5c ebp=0290ff88 iopl=0         nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

77ef3258 cc              int     3

0:002> ~1s

eax=00017355 ebx=00000000 ecx=0002e6ab edx=0040105f esi=00000000 edi=0280ff28

eip=00401cd3 esp=0280fed8 ebp=0280ff28 iopl=0         nv up ei ng nz na po cy

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000283

test!d+0x33:

00401cd3 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:0280ff30=0002e6ab

0:001> k

ChildEBP RetAddr  

0280ff28 00401d33 test!d+0x33 [E:\test\test\testDlg.cpp @ 182]

0280ff88 77e31154 test!Test+0x33 [E:\test\test\testDlg.cpp @ 194]

WARNING: Stack unwind information not available. Following frames may be wrong.

0280ff94 77f1b299 kernel32!BaseThreadInitThunk+0x12

0280ffd4 77f1b26c ntdll!__RtlUserThreadStart+0x70

0280ffec 00000000 ntdll!_RtlUserThreadStart+0x1b

多次截取1号线程调用栈,发现其一直在test!d函数执行,怀疑d函数调用存在性能瓶颈。

步聚3:修改代码指令,屏敝对问题函数的调用

修改前指令:

修改后指令:

此时进程testpid=3032)程序占用的cpu0,屏敝对函数d的调用,cpu下降达到30!!!

至此说明函数d执行效率较差,应做优化。

Ps 以上方法适用于不允许重启进程的情况下操作

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值