自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

性能優(yōu)化-一個(gè)命令發(fā)現(xiàn)性能問(wèn)題

系統(tǒng) Linux
為了取得程序的一丁點(diǎn)性能提升而大幅度增加技術(shù)的復(fù)雜性和晦澀性能,這個(gè)買(mǎi)賣(mài)做不得,這不僅僅是因?yàn)閺?fù)雜的代碼容器滋生bug,也因?yàn)樗麜?huì)使日后的閱讀和維護(hù)工作要更加艱難。

[[339022]]

本文轉(zhuǎn)載自微信公眾號(hào)「編程珠璣」,作者守望先生 。轉(zhuǎn)載本文請(qǐng)聯(lián)系編程珠璣公眾號(hào)。  

原文鏈接:https://mp.weixin.qq.com/s/pZtqz2tl4ArbCnzdDdDPwQ

為了取得程序的一丁點(diǎn)性能提升而大幅度增加技術(shù)的復(fù)雜性和晦澀性能,這個(gè)買(mǎi)賣(mài)做不得,這不僅僅是因?yàn)閺?fù)雜的代碼容器滋生bug,也因?yàn)樗麜?huì)使日后的閱讀和維護(hù)工作要更加艱難。

為什么要性能優(yōu)化

也許是想要支持更高的吞吐量,想要更小的延遲,或者提高資源的利用率等,這些都是性能優(yōu)化的目標(biāo)之一。不過(guò)需要提醒的是,不要過(guò)早的進(jìn)行性能優(yōu)化。如果當(dāng)前并沒(méi)有任何性能問(wèn)題,又何必耗費(fèi)這個(gè)精力呢?當(dāng)前一些有助于提高性能的編碼習(xí)慣還是可以時(shí)刻保持的。

目標(biāo)

全面的性能優(yōu)化不是一件簡(jiǎn)單的事情。本系列文章不在于介紹性能優(yōu)化原理或者特定的算法優(yōu)化。旨在分享一些實(shí)踐中常用到的技巧,同時(shí)也主要關(guān)注CPU方面。

如何發(fā)現(xiàn)性能瓶頸

解決性能問(wèn)題的第一步是發(fā)現(xiàn)性能問(wèn)題。如何快速發(fā)現(xiàn)性能問(wèn)題呢?對(duì)于本文來(lái)說(shuō),如何發(fā)現(xiàn)那些使CPU不停地瞎忙的代碼呢?為什么這里是說(shuō)讓CPU瞎忙的代碼?

舉個(gè)例子,完成某個(gè)事情,你可能只需要一個(gè)CPU時(shí)間片,但是由于代碼不夠好,使得仍然需要多個(gè)CPU時(shí)間片。導(dǎo)致CPU非常忙碌,而無(wú)法繼續(xù)提高它的效率。

top

這個(gè)命令相信大家都用過(guò),可以實(shí)時(shí)看到進(jìn)程的一些狀態(tài)。它的使用方法有很多文章不厭其煩地對(duì)其進(jìn)行了介紹,本文不打算進(jìn)行介紹。我們可以通過(guò)top命令看到某個(gè)進(jìn)程占用的CPU,但是CPU占用高并不代表它有性能問(wèn)題,也有可能是CPU正在有效地高速運(yùn)轉(zhuǎn),并沒(méi)有占著茅坑不拉屎。

快速發(fā)現(xiàn)

想必我們都聽(tīng)過(guò)八二法則,同樣的,80%的性能問(wèn)題集中于20%的代碼。因此我們只要找到這20%的部分代碼,就可以有效地解決一些性能問(wèn)題。

本文使用perf命令,它很強(qiáng)大,支持的參數(shù)也非常多,不過(guò)沒(méi)關(guān)系,本文也沒(méi)打算全部介紹。

系統(tǒng)中可能沒(méi)有perf命令,ubuntu可以使用如下方法安裝:

  1. sudo apt install linux-tools-common 

實(shí)例

直接來(lái)看示例吧。例子很簡(jiǎn)單,只是將字符串的字母轉(zhuǎn)為大寫(xiě)罷了。當(dāng)然了,很多人可能一眼就看出了哪里有性能問(wèn)題,不過(guò)沒(méi)關(guān)系,這個(gè)例子只是為了說(shuō)明perf的應(yīng)用。

  1. //來(lái)源:公眾號(hào)【編程珠璣】 
  2. //作者:守望先生 
  3. //toUpper.c 
  4. #include<stdlib.h> 
  5. #include<stdio.h> 
  6. #include<time.h> 
  7. #include<ctype.h> 
  8. #include<string.h> 
  9. #include<sys/time.h> 
  10. #define MAX_LEN  1024*1024 
  11. void printCostTime(struct timeval *start,struct timeval *end
  12.     if(NULL == start || NULL == end
  13.     { 
  14.         return
  15.     } 
  16.     long cost = (end->tv_sec - start->tv_sec) * 1000 + (end->tv_usec - start->tv_usec)/1000; 
  17.     printf("cost time: %ld ms\n",cost); 
  18. int main(void) 
  19.     srand(time(NULL)); 
  20.     int min = 'a'
  21.     int max = 'z'
  22.     char *str = malloc(MAX_LEN); 
  23.     //申請(qǐng)失敗則退出 
  24.     if(NULL == str) 
  25.     { 
  26.         printf("failed\n"); 
  27.         return -1; 
  28.     } 
  29.     unsigned int i = 0; 
  30.     while(i < MAX_LEN)//生成隨機(jī)數(shù) 
  31.     { 
  32.         str[i] = ( rand() % ( max - min ) ) + min
  33.         i++; 
  34.     } 
  35.     str[MAX_LEN - 1] = 0;  
  36.     struct timeval start,end
  37.     gettimeofday(&start,NULL); 
  38.     for(i = 0;i < strlen(str) ;i++) 
  39.     { 
  40.         str[i]  = toupper( str[i] ); 
  41.     } 
  42.     gettimeofday(&end,NULL); 
  43.     printCostTime(&start,&end); 
  44.     free(str); 
  45.     str = NULL
  46.     return 0; 

編譯成可執(zhí)行程序并運(yùn)行:

  1. $ gcc -o toUpper toUpper.c 
  2. $ ./toUpper 

這個(gè)時(shí)候我們用top查看結(jié)果發(fā)現(xiàn)toUpper程序占用CPU 100%:

  1. top -p `pidof toUpper` 
  2.   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND      
  3. 24456 root       20   0    5248   2044    952 R 100.0  0.0   0:07.13 toUpper   

打開(kāi)另外一個(gè)終端,執(zhí)行命令:

  1. $ perf top -p `pidof toUpper` 
  2. Samples: 1K of event 'cycles:ppp', Event count (approx.): 657599945 
  3. Overhead  Shared Object  Symbol 
  4.   99.13%  libc-2.23.so   [.] strlen 
  5.    0.19%  [kernel]       [k] perf_event_task_tick 
  6.    0.11%  [kernel]       [k] prepare_exit_to_usermode 
  7.    0.10%  libc-2.23.so   [.] toupper 
  8.    0.09%  [kernel]       [k] rcu_check_callbacks 
  9.    0.09%  [kernel]       [k] reweight_entity 
  10.    0.09%  [kernel]       [k] task_tick_fair 
  11.    0.09%  [kernel]       [k] native_write_msr 
  12.    0.09%  [kernel]       [k] trigger_load_balance 
  13.    0.00%  [kernel]       [k] native_apic_mem_write 
  14.    0.00%  [kernel]       [k] __perf_event_enable 
  15.    0.00%  [kernel]       [k] intel_bts_enable_local 

其中pidof命令用于獲取指定程序名的進(jìn)程ID。

看到結(jié)果了嗎?可以很清楚地看到,strlen函數(shù)占用了整個(gè)程序99%的CPU,那這個(gè)CPU的占用是否可以優(yōu)化掉呢?我們現(xiàn)在都清楚,顯然是可以的,在對(duì)每一個(gè)字符串進(jìn)行大寫(xiě)轉(zhuǎn)換時(shí),都進(jìn)行了字符串長(zhǎng)度的計(jì)算,顯然是沒(méi)有必要,可以拿到循環(huán)之外的。

同時(shí)我們也關(guān)注到,這里面有很多符號(hào)可能完全沒(méi)見(jiàn)過(guò),不知道什么含義了,比例如reweight_entity,不過(guò)我們知道它前面有著kernel字樣,因此也就明白,這是內(nèi)核干的事情,僅此而已。

這里實(shí)時(shí)查看的方法,當(dāng)然你也可以保存信息進(jìn)行查看。

  1. $ perf record -e cycles -p `pidof toUpper` -g -a 

執(zhí)行上面的命令一段時(shí)間,用于采集相關(guān)性能和符號(hào)信息,隨后ctrl+c中止。默認(rèn)當(dāng)前目錄下生成perf.data,不過(guò)這里面的數(shù)據(jù)不易閱讀,因此執(zhí)行:

  1. $ perf report 
  2. +  100.00%     0.00%  toUpper  [unknown]          [k] 0x03ee258d4c544155 
  3. +  100.00%     0.00%  toUpper  libc-2.23.so       [.] __libc_start_main 
  4. +   99.72%    99.34%  toUpper  libc-2.23.so       [.] strlen 
  5.      0.21%     0.02%  toUpper  [kernel.kallsyms]  [k] apic_timer_interrupt 
  6.      0.19%     0.00%  toUpper  [kernel.kallsyms]  [k] smp_apic_timer_interrupt 
  7.      0.16%     0.00%  toUpper  [kernel.kallsyms]  [k] ret_from_intr 
  8.      0.16%     0.00%  toUpper  [kernel.kallsyms]  [k] hrtimer_interrupt 
  9.      0.16%     0.00%  toUpper  [kernel.kallsyms]  [k] do_IRQ 
  10.      0.15%     0.15%  toUpper  libc-2.23.so       [.] toupper 
  11.      0.15%     0.00%  toUpper  [kernel.kallsyms]  [k] handle_irq 
  12.      0.15%     0.00%  toUpper  [kernel.kallsyms]  [k] handle_edge_irq 
  13.      0.15%     0.00%  toUpper  [kernel.kallsyms]  [k] handle_irq_event 
  14.      0.15%     0.00%  toUpper  [kernel.kallsyms]  [k] handle_irq_event_percpu 
  15.      0.14%     0.00%  toUpper  [kernel.kallsyms]  [k] __handle_irq_event_percpu 
  16.      0.14%     0.01%  toUpper  [kernel.kallsyms]  [k] __hrtimer_run_queues 
  17.      0.13%     0.00%  toUpper  [kernel.kallsyms]  [k] _rtl_pci_interrupt 

其中-g參數(shù)為了保存調(diào)用調(diào)用鏈,-a表示保存所有CPU信息。

因此就可以看到采樣信息了,怎么樣是不是很明顯,其中的+部分還可以展開(kāi),看到調(diào)用鏈。

例如展開(kāi)的部分信息如下:

  1. -  100.00%     0.00%  toUpper  libc-2.23.so       [.] __libc_start_main         
  2.    - __libc_start_main                                                          
  3.         99.72% strlen   

當(dāng)然了,實(shí)際上你也可以將結(jié)果重定向到另外一個(gè)文件,便于查看:

  1. $ perf report > result 
  2. $ more result 
  3. # Event count (approx.): 23881569776 
  4. # Children      Self  Command  Shared Object      Symbol                         
  5.  
  6. # ........  ........  .......  .................  .............................. 
  7. ................... 
  8.    100.00%     0.00%  toUpper  [unknown]          [k] 0x03ee258d4c544155 
  9.             | 
  10.             ---0x3ee258d4c544155 
  11.                __libc_start_main 
  12.                |           
  13.                 --99.72%--strlen 
  14.  
  15.    100.00%     0.00%  toUpper  libc-2.23.so       [.] __libc_start_main 
  16.             | 
  17.             ---__libc_start_main 
  18.                |           
  19.                 --99.72%--strlen 
  20.  
  21.     99.72%    99.34%  toUpper  libc-2.23.so       [.] strlen 
  22.             |           
  23.              --99.34%--0x3ee258d4c544155 

這樣看也是非常清晰的。

不過(guò)不要高興地太早,并不是所有情況都能清晰的看到具體問(wèn)題在哪里的。

至于本文例子的性能問(wèn)題怎么解決,相信你已經(jīng)很清楚了,只需要把strlen提到循環(huán)外即可,這里不再贅述。

總結(jié)

 

本文的例子過(guò)于簡(jiǎn)單粗暴,但是足夠說(shuō)明perf的使用,快速發(fā)現(xiàn)程序中占用CPU較高的部分,至于該部分能否被優(yōu)化,是否正常就需要進(jìn)一步分析了。不過(guò)別急,后續(xù)將會(huì)分享一些常見(jiàn)的可優(yōu)化的性能點(diǎn)。

作者:守望,linux應(yīng)用開(kāi)發(fā)者,目前在公眾號(hào)【編程珠璣】 分享Linux/C/C++/數(shù)據(jù)結(jié)構(gòu)與算法/工具等原創(chuàng)技術(shù)文章和學(xué)習(xí)資源。

 

責(zé)任編輯:武曉燕 來(lái)源: 編程珠璣
相關(guān)推薦

2024-02-22 16:55:13

2022-07-15 08:52:03

Linux優(yōu)化

2021-12-29 08:21:01

Performance優(yōu)化案例工具

2022-04-08 09:47:55

性能優(yōu)化開(kāi)發(fā)

2011-04-25 09:11:15

2020-06-05 08:53:31

接口性能實(shí)踐

2021-03-16 10:20:56

監(jiān)控系統(tǒng)架構(gòu)技術(shù)

2021-05-17 11:55:48

監(jiān)控命令Linux

2018-11-22 15:07:17

代碼github程序

2011-05-03 10:17:25

CSS

2021-05-12 06:02:56

性能優(yōu)化工具WebPageTest

2021-05-10 08:08:25

工具LightHouse性能優(yōu)化

2024-09-04 14:28:20

Python代碼

2009-09-08 09:45:23

App Engine性

2022-02-16 14:10:51

服務(wù)器性能優(yōu)化Linux

2021-11-29 11:13:45

服務(wù)器網(wǎng)絡(luò)性能

2017-08-08 09:45:43

Python性能優(yōu)化

2009-06-16 16:10:59

Hibernate性能

2013-06-09 15:31:35

jQueryjQuery優(yōu)化性能優(yōu)化

2020-09-19 21:26:56

webpack
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)