Linux下高cpu实施方案,寻找程序cpu使用率高的原故

by admin on 2019年8月29日

Linux下高cpu实施方案,寻找程序cpu使用率高的原故。Linux下高cpu技术方案,Linuxcpu应用方案

前些天解决了一个九千0殷切的issue,客商抱怨产品进级后系统会变慢和CPU使用率相当高,顾客天性相当的大,声称不遥遥抢先缓和那个标题就退货,弄得大家卡宴&D压力相当的大,化解这么些issue的义务分给了自家,客商是南非共和国(The Republic of South Africa)的七个铺面,由于时差难题,小编只幸亏家远程化解难点,早晨8点半用
gotomeeting远程到客商Computer查看大家的体系,折腾了四个多时辰,终于在早上时reproduce了这一个high
CPU,赶紧抓Log,用wireshark抓包,用gcore,gstack,strace和top保存了系统的有关输出。在第2天分析了那么些文件后,
找到了产品的bug,代码的撰稿人分配了10K的缓冲区,并想当然以为10K足以够用,当然99%的气象下是够用的,不过在那1%的景象下冒出了难题,缓冲
区不幸被写满了,然后程序步入了死循环,导致high
CPU。找到了难题了,fix就很轻松了,顾客的秉性也温度下跌了,fix异常的快就能够deliver给客商。反思消除难题的进度,感到这一个深入分析进程具备可复用
性,值得总计一下。

1.用top命令查看哪个过程占用CPU高
gateway网关进程14094占用CPU高达891%,那个数值是进度内各样线程占用CPU的累加值。

  PID USER      PR  NI  VIRT  RES  SHR S %CPU
%MEM    TIME+  COMMAND    
14094 root      15   0  315m  10m 7308 S 891%  2.2   1:49.01
gateway                                                                                 
20642 root      17   0 17784 4148 2220 S  0.5  0.8   2:39.96
microdasys                                                                                     
 1679 root      18   0 10984 1856 1556 R  0.3  0.4   0:22.21
sshd                                                                                            
22563 root      18   0  2424 1060  800 R  0.3  0.2   0:00.03
top                                                                                             
    1 root      18   0  2156  492  460 S  0.0  0.1   0:01.59 init       

2.用top -H -p pid命令查看进度内各种线程占用的CPU百分比

#top -H -p 14094
top中能够见见有107个线程,可是上边9个线程占用CPU极高,上边以线程14086为主,分析其为啥high
CPU

  PID USER      PR  NI  VIRT  RES  SHR S %CPU
MEM    TIME+  COMMAND                         

14086 root      25   0  922m 914m 538m R  101 10.0  21:35.46
gateway                          

14087 root      25   0  922m 914m 538m R  101 10.0  10:50.22
gateway                           

14081 root      25   0  922m 914m 538m S   99 10.0   8:57.36
gateway                            

14082 root      25   0  922m 914m 538m R   99 10.0  11:51.92
gateway                              

14089 root      25   0  922m 914m 538m R   99 10.0  21:21.77
gateway                             

14092 root      25   0  922m 914m 538m R   99 10.0  19:55.47
gateway                               

14094 root      25   0  922m 914m 538m R   99 10.0  21:02.21
gateway                                

14083 root      25   0  922m 914m 538m R   97 10.0  21:32.39
gateway                                 

14088  root       25   0   922m 914m  538m
R    97 10.0   11:23.12  gateway

3.采纳gstack命令查看进程中各线程的函数调用栈
#gstack 14094 > gstack.log
在gstack.log中查找线程ID14086,由于函数栈会暴光函数细节,因而只突显了五个函数桢,线程ID14086对应线程号是37

Thread 37 (Thread 0x4696ab90 (LWP 14086)):
#0  0x40000410 in __kernel_vsyscall ()
#1  0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6

4.选择gcore命令转存进程映像及内存上下文

#gcore 14094
该命令生成core文件core.14094

5。用strace命令查看系统调用和花费的日子
#strace -T -r -c -p 14094

-c参数字呈现示总计新闻,去掉此参数能够查阅各样系统调用话费的小时及重临值。

% time     seconds  usecs/call     calls    errors        syscall



99.99   22.683879        3385      6702                     poll

  0.00    0.001132           0      6702                     gettimeofday

  0.00    0.000127           1       208       208          accept

  0.00    0.000022          22         1                    read

  0.00    0.000000           0         1                    write

  0.00    0.000000           0         1                    close

  0.00    0.000000           0        14                    time

  0.00    0.000000           0         2                    stat64

  0.00    0.000000           0         4                    clock_gettime

  0.00    0.000000           0         7                    send

  0.00    0.000000           0        10        10          recvfrom



100.00   22.685160                 13652       218 total

6.用gdb调节和测验core文件,并线程切换成37号线程
gcore和实在的core
dump时发出的core文件大概同样,只是不能够用gdb进行一些动态调节和测量试验

(gdb) gdb gateway core.14094
(gdb) thread 37
[Switching to thread 37 (Thread 0x4696ab90 (LWP
14086))]#0  0x40000410 in __kernel_vsyscall ()
(gdb) where
#0  0x40000410 in __kernel_vsyscall ()
#1  0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6
能够依附详细的函数栈实行gdb调节和测量检验,打字与印刷一些变量值,并整合源代码剖析为啥会poll调用占用极高的CPU。
因为代码涉及到厂家产权,顾不在此做详细分析,须要领悟的是剖析的流水生产线和使用的通令。

流程为:进程ID->线程ID->线程函数调用栈->函数耗时和调用计算->源代码深入分析

后日消除了二个八万迫切的issue,顾客抱怨产品晋级后系统会变慢和CPU使用率非常高,客商本性一点都不小,…

linux进度高cpu难点深入分析

确定是CPU过高

小说出处:

 

Linux下高cpu实施方案,寻找程序cpu使用率高的原故。利用top观看是还是不是留存CPU使用率过高现象

 

1.用top命令查看哪个进度占用CPU高

寻找线程

 

gateway网关进程14094占为己有CPU高达891%,这些数值是进程内各种线程占用CPU的累加值。

对CPU使用率过高的历程的装有线程进行排序

您的软件在有些时刻截至服务,CPU占用达到百分百+,这种难点三个恐怕的来由是发出了死循环,要是程序某处存在潜在的死循环,并在某种条件下会引发,本文以一个演示来恒定出现死循环的职位。
当程序某处存在死循环,平常定位难题及裁减范围的法子是,在思疑的代码处加log,可能注释掉疑心代码,那对于轻巧复发难点的顺序来讲幸好,但对于“临时”才会时有产生难题前后相继却很难调节和测量检验,因为我们很难重现程序故障。本文所述的调解进程正是在这种情形下,即使难题早就现身,大家要求遭遇保证现场,即出难题的主次还在运营中。

 

ps H -e -o pid,tid,pcpu,cmd –sort=pcpu |grep
xxx获得如下结果,当中线程2909使用了7.8%的CPU. 2907 2913 0.0 ./xxx 2907
2909 7.8 ./xxx也足以透过翻看/proc中的新闻来分明高CPU线程.
打字与印刷了4列,线程ID,线程名,客户时间和基本时间(排行未分先后) awk ‘{print
$1,$2,$14,$15}’ /proc/2907/task/*/stat

1.我们首先要精晓是哪个线程出了难题:
先是查一下出难点经过的pid,举个例子

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND  
  

找寻调用栈

ovtsvn@ovtsvn:~/MASS4/src/icdn/src$ ps -ef | grep icdn home88一必发 1

14094 root      15   0  315m  10m 7308 S 891%  2.2   1:49.01 gateway    
                                                                       
    

选择gdb attach nmsagent所在的长河,在gdb中运用 info threads彰显全数线程

ovtsvn   11065     1 50 11:57 ?        00:00:07 ./icdn home88一必发 2

20642 root      17   0 17784 4148 2220 S  0.5  0.8   2:39.96 microdasys
                                                                       
             

gdb

ovtsvn   11076 10971  0 11:57 pts/2    00:00:00 grep

 1679 root      18   0 10984 1856 1556 R  0.3  0.4   0:22.21 sshd      
                                                                       
             

gdb>attach 2907

ovtsvn@ovtsvn:~/MASS4/src/icdn/src$

22563 root      18   0  2424 1060  800 R  0.3  0.2   0:00.03 top        
                                                                       
            

gdb>info threads

ovtsvn@ovtsvn:~/MASS4/src/icdn/src$ 

    1 root      18   0  2156  492  460 S  0.0  0.1   0:01.59 init       

收获如下结果,能够开采2909线程的号码是12

然后top命令查看线程音信:
top -H -p 11065

 

  13 Thread 0xad5f2b70 (LWP 2908)  0x004ef0d7 in mq_timedreceive ()
from /lib/tls/i686/cmov/librt.so.1

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                 home88一必发 3

2.用top -H -p pid命令查看进程内千家万户线程占用的CPU百分比

  12 Thread 0xad58eb70 (LWP 2909)  0x006e0422 in __kernel_vsyscall ()

11073 ovtsvn    25   0  325m 3980 2236 R  100  0.4   1:40.84 icdn                                                                    home88一必发 4

 

  11 Thread 0xad52ab70 (LWP 2910)  0x006e0422 in __kernel_vsyscall ()

11065 ovtsvn    18   0  325m 3980 2236 S    0  0.4   0:00.01 icdn                                                                    home88一必发 5

#top -H -p 14094

  10 Thread 0xad4f8b70 (LWP 2911)  0x006e0422 in __kernel_vsyscall ()

11066 ovtsvn    18   0  325m 3980 2236 S    0  0.4   0:00.00 icdn                                                                    home88一必发 6

top中能够见见有107个线程,可是下边9个线程占用CPU异常高,上边以线程14086为主,深入分析其为啥high
CPU

  9 Thread 0xad4c6b70 (LWP 2912)  0x006e0422 in __kernel_vsyscall ()

11067 ovtsvn    15   0  325m 3980 2236 S    0  0.4   0:00.00 icdn                                                                    home88一必发 7

 

  8 Thread 0xad3feb70 (LWP 2913)  0x004ef0d7 in mq_timedreceive () from
/lib/tls/i686/cmov/librt.so.1

11068 ovtsvn    15   0  325m 3980 2236 S    0  0.4   0:00.00 icdn                                                                    home88一必发 8

  PID USER      PR  NI  VIRT  RES  SHR S %CPU MEM    TIME+  COMMAND    
                    

  7 Thread 0xace08b70 (LWP 2914)  0x004ef0d7 in mq_timedreceive () from
/lib/tls/i686/cmov/librt.so.1

11069 ovtsvn 180 325m 39802236 S 00.40:00.00 icdn home88一必发 9

 

  6 Thread 0xac607b70 (LWP 2915)  0x006e0422 in __kernel_vsyscall ()

11070 ovtsvn 180 325m 39802236 S 00.40:00.00 icdn home88一必发 10

14086 root      25   0  922m 914m 538m R  101 10.0  21:35.46 gateway    
                     

  5 Thread 0xac5e6b70 (LWP 2916)  0x006e0422 in __kernel_vsyscall ()

11071 ovtsvn 220 325m 39802236 S 00.40:00.00 icdn home88一必发 11

 

  4 Thread 0xac361b70 (LWP 2917)  0x006e0422 in __kernel_vsyscall ()

home88一必发,11072 ovtsvn 150 325m 39802236 R 00.40:00.00 icdn

14087 root      25   0  922m 914m 538m R  101 10.0  10:50.22 gateway    
                      

  3 Thread 0xac2fdb70 (LWP 2918)  0x006e0422 in __kernel_vsyscall ()

 

 

  2 Thread 0xac1fcb70 (LWP 2919)  0x004ef0d7 in mq_timedreceive () from
/lib/tls/i686/cmov/librt.so.1

从地点可以看到,出标题线程PID为11073

14081 root      25   0  922m 914m 538m S   99 10.0   8:57.36 gateway    
                       

* 1 Thread 0xb78496d0 (LWP 2907)  0x006e0422 in __kernel_vsyscall ()

2.接下来,大家用gdb来attach指标经过
执行: gdb icdn 11065
在gdb中,列出线程状态:

 

行使thread 切换线程,使用bt显示线程栈

home88一必发 12(gdb) info threads home88一必发 13  

14082 root      25   0  922m 914m 538m R   99 10.0  11:51.92 gateway    
                         

gdb>thread 12

9 Thread 47056948181264 (LWP 11066)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 home88一必发 14  

 

gdb>bt

8 Thread 47056956573968 (LWP 11067)  0x00002acc4a406fc2 in select () from /lib/libc.so.6 home88一必发 15  

14089 root      25   0  922m 914m 538m R   99 10.0  21:21.77 gateway    
                        

收获如下线程栈

7 Thread 47056964966672 (LWP 11068)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 home88一必发 16 

 

#0  0x006e0422 in __kernel_vsyscall ()

 6 Thread 47056973359376 (LWP 11069)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 home88一必发 17  

14092 root      25   0  922m 914m 538m R   99 10.0  19:55.47 gateway    
                          

#1  0x001cca26 in nanosleep () from /lib/tls/i686/cmov/libc.so.6

5 Thread 47056981752080 (LWP 11070)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 home88一必发 18  

 

#2  0x001fc2dc in usleep () from /lib/tls/i686/cmov/libc.so.6

4 Thread 47056990144784 (LWP 11071)  0x00002acc4a40e63c in recvfrom () from /lib/libc.so.6 home88一必发 19  

14094 root      25   0  922m 914m 538m R   99 10.0  21:02.21 gateway    
                           

#3  0x0806b510 in OspTaskDelay ()

3 Thread 47057194060048 (LWP 11072)  0x00002acc4a406fc2 in select () from /lib/libc.so.6 home88一必发 20  

 

#4  0x0805c710 in CDispatchTask::NodeMsgSendToSock() ()

2 Thread 47057226893584 (LWP 11073)  CSendFile::SendFile (this=0x2acc5d4aff40, pathname=@0x2acc5d4afee0) home88一必发 21    at ../src/csendfile.cpp:101 home88一必发 22  

14083 root      25   0  922m 914m 538m R   97 10.0  21:32.39 gateway    
                            

#5  0x0805cc74 in DispatchTaskEntry ()

1 Thread 47056939784832 (LWP 11065)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 home88一必发 23(gdb) 

 

#6  0x0806a8e9 in OspTaskTemplateFunc(void*) ()

gdb已经列出了各线程正在实践的函数,大家要求更加的多音讯,记住11073对应的行首标号,那是gdb为线程分配的id,这里为2,然后推行切换:

14088  root       25   0   922m 914m  538m R    97 10.0   11:23.12
 gateway

#7  0x00d4780e in start_thread () from
/lib/tls/i686/cmov/libpthread.so.0

(gdb) thread 2 home88一必发 24

 

 #8  0x002027ee in clone () from /lib/tls/i686/cmov/libc.so.6

[Switching to thread 2 (Thread 47057226893584 (LWP 11073))]#0  CSendFile::SendFile (this=0x2acc5d4aff40, pathname=@0x2acc5d4afee0) home88一必发 25    at ../src/csendfile.cpp:101 home88一必发 26101             while(1) home88一必发 27

3.选拔gstack命令查看进程中各线程的函数调用栈

 ps + strace

(gdb) 

#gstack 14094 > gstack.log

获得进程ID 21465

bt一下:

在gstack.log中查找线程ID14086,由于函数栈会揭露函数细节,由此只展现了多个函数桢,线程ID14086对应线程号是37

ps -e |grep cmu

home88一必发 28(gdb) bt home88一必发 29

 

 4996 ?        00:00:25 cmu_fjga_sp3

#0  CSendFile::SendFile (this=0x2acc5d4aff40, pathname=@0x2acc5d4afee0) at ../src/csendfile.cpp:101 home88一必发 30

Thread 37 (Thread 0x4696ab90 (LWP 14086)):

21465 pts/5    00:08:10 cmu

#1  0x000000000040592e in CIcdn::TaskThread (pParam=0x7fff617eafe0) at ../src/cicdn.cpp:128 home88一必发 31

#0  0x40000410 in __kernel_vsyscall ()

获得线程时间, 当中最占CPU的是 EpollRecvTask 21581

#2  0x00002acc4a90b73a in start_thread () from /lib/libpthread.so.0 home88一必发 32

#1  0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6

ps -eL |grep 21465 21465 21579 pts/5 00:00:00 CamApp 21465 21580 pts/5
00:00:00 TimerMan Task 21465 21581 pts/5 00:09:02 EpollRecvTask 21465
21582 pts/5 00:00:00 使用 strace -p 21581 获得线程栈

#3  0x00002acc4a40d6dd in clone () from /lib/libc.so.6 home88一必发 33

 

#4  0x0000000000000000 in ?? ()

4.运用gcore命令转存进程印象及内存上下文

来看一下101行的代码:

 

home88一必发 34(gdb) l home88一必发 35

#gcore 14094

96      } home88一必发 36

该命令生成core文件core.14094

97 home88一必发 37

 

98      int CSendFile::SendFile(const string& pathname) home88一必发 38

 

99      {

5。用strace命令查看系统调用和花费的时间

100             int n;

#strace -T -r -c -p 14094

101             while(1)

 

102             {

 

103                     n++;

通用的总体用法:

104             }

 

105             //read file and send 

strace -o output.txt -T -tt -e trace=all -p $pid

现在大家从来到了出标题标代码地点,这里的巡回只用来演示的。 
最终别忘了detach()

地点的意思是 追踪28979经过的全部系统调用(-e
trace=all),并计算体系调用的花费时间,以及起先时间(并以可视化的时分秒格式呈现),最终将记录结果存在output.txt文件之中。

调解完内定进度后,能够运转detach命令来让GDB释放该进度,该进程得以持续运营。当回车时,detach不会重复。当实施完detach后,进度和GDB不再相关,GDB能够attach别的进度。

 

 

 

-c参数字显示示总计消息,去掉此参数能够查看各类系统调用话费的大运及重临值。

 

% time     seconds  usecs/call     calls    errors        syscall

 



 

99.99   22.683879        3385      6702                     poll

 

  0.00    0.001132           0      6702                    
gettimeofday

 

  0.00    0.000127           1       208       208          accept

 

  0.00    0.000022          22         1                    read

 

  0.00    0.000000           0         1                    write

 

  0.00    0.000000           0         1                    close

 

  0.00    0.000000           0        14                    time

 

  0.00    0.000000           0         2                    stat64

 

  0.00    0.000000           0         4                  
 clock_gettime

 

  0.00    0.000000           0         7                    send

 

  0.00    0.000000           0        10        10          recvfrom

 



 

100.00   22.685160                 13652       218 total

 

 

 

 

6.用gdb调节和测量检验core文件,并线程切换来37号线程

gcore和实在的core
dump时产生的core文件差十分的少一样,只是不可能用gdb举行一些动态调节和测验

 

(gdb) gdb gateway core.14094 

(gdb) thread 37

[Switching to thread 37 (Thread 0x4696ab90 (LWP 14086))]#0
 0x40000410 in __kernel_vsyscall ()

(gdb) where

#0  0x40000410 in __kernel_vsyscall ()

#1  0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6

 

可以依靠详细的函数栈进行gdb调试,打字与印刷一些变量值,并结合源代码分析为什么会poll调用占用异常高的CPU。

 

1.用top命令查看哪个进程占用CPU高
gateway网关进度14094据为己有CPU高达891%,这么些数值是进度内相继线程占用CPU的累加值。…

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图