成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

性能優化-一個命令發現性能問題

系統 Linux
為了取得程序的一丁點性能提升而大幅度增加技術的復雜性和晦澀性能,這個買賣做不得,這不僅僅是因為復雜的代碼容器滋生bug,也因為他會使日后的閱讀和維護工作要更加艱難。

[[339022]]

本文轉載自微信公眾號「編程珠璣」,作者守望先生 。轉載本文請聯系編程珠璣公眾號。  

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

為了取得程序的一丁點性能提升而大幅度增加技術的復雜性和晦澀性能,這個買賣做不得,這不僅僅是因為復雜的代碼容器滋生bug,也因為他會使日后的閱讀和維護工作要更加艱難。

為什么要性能優化

也許是想要支持更高的吞吐量,想要更小的延遲,或者提高資源的利用率等,這些都是性能優化的目標之一。不過需要提醒的是,不要過早的進行性能優化。如果當前并沒有任何性能問題,又何必耗費這個精力呢?當前一些有助于提高性能的編碼習慣還是可以時刻保持的。

目標

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

如何發現性能瓶頸

解決性能問題的第一步是發現性能問題。如何快速發現性能問題呢?對于本文來說,如何發現那些使CPU不停地瞎忙的代碼呢?為什么這里是說讓CPU瞎忙的代碼?

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

top

這個命令相信大家都用過,可以實時看到進程的一些狀態。它的使用方法有很多文章不厭其煩地對其進行了介紹,本文不打算進行介紹。我們可以通過top命令看到某個進程占用的CPU,但是CPU占用高并不代表它有性能問題,也有可能是CPU正在有效地高速運轉,并沒有占著茅坑不拉屎。

快速發現

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

本文使用perf命令,它很強大,支持的參數也非常多,不過沒關系,本文也沒打算全部介紹。

系統中可能沒有perf命令,ubuntu可以使用如下方法安裝:

  1. sudo apt install linux-tools-common 

實例

直接來看示例吧。例子很簡單,只是將字符串的字母轉為大寫罷了。當然了,很多人可能一眼就看出了哪里有性能問題,不過沒關系,這個例子只是為了說明perf的應用。

  1. //來源:公眾號【編程珠璣】 
  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.     //申請失敗則退出 
  24.     if(NULL == str) 
  25.     { 
  26.         printf("failed\n"); 
  27.         return -1; 
  28.     } 
  29.     unsigned int i = 0; 
  30.     while(i < MAX_LEN)//生成隨機數 
  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; 

編譯成可執行程序并運行:

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

這個時候我們用top查看結果發現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   

打開另外一個終端,執行命令:

  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命令用于獲取指定程序名的進程ID。

看到結果了嗎?可以很清楚地看到,strlen函數占用了整個程序99%的CPU,那這個CPU的占用是否可以優化掉呢?我們現在都清楚,顯然是可以的,在對每一個字符串進行大寫轉換時,都進行了字符串長度的計算,顯然是沒有必要,可以拿到循環之外的。

同時我們也關注到,這里面有很多符號可能完全沒見過,不知道什么含義了,比例如reweight_entity,不過我們知道它前面有著kernel字樣,因此也就明白,這是內核干的事情,僅此而已。

這里實時查看的方法,當然你也可以保存信息進行查看。

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

執行上面的命令一段時間,用于采集相關性能和符號信息,隨后ctrl+c中止。默認當前目錄下生成perf.data,不過這里面的數據不易閱讀,因此執行:

  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參數為了保存調用調用鏈,-a表示保存所有CPU信息。

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

例如展開的部分信息如下:

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

當然了,實際上你也可以將結果重定向到另外一個文件,便于查看:

  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 

這樣看也是非常清晰的。

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

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

總結

 

本文的例子過于簡單粗暴,但是足夠說明perf的使用,快速發現程序中占用CPU較高的部分,至于該部分能否被優化,是否正常就需要進一步分析了。不過別急,后續將會分享一些常見的可優化的性能點。

作者:守望,linux應用開發者,目前在公眾號【編程珠璣】 分享Linux/C/C++/數據結構與算法/工具等原創技術文章和學習資源。

 

責任編輯:武曉燕 來源: 編程珠璣
相關推薦

2024-02-22 16:55:13

2022-07-15 08:52:03

Linux優化

2021-12-29 08:21:01

Performance優化案例工具

2022-04-08 09:47:55

性能優化開發

2011-04-25 09:11:15

2018-11-22 15:07:17

代碼github程序

2020-06-05 08:53:31

接口性能實踐

2021-05-12 06:02:56

性能優化工具WebPageTest

2025-06-03 00:00:06

性能優化性能指標響應時間

2021-05-17 11:55:48

監控命令Linux

2021-03-16 10:20:56

監控系統架構技術

2021-05-10 08:08:25

工具LightHouse性能優化

2011-05-03 10:17:25

CSS

2013-06-09 15:31:35

jQueryjQuery優化性能優化

2017-08-08 09:45:43

Python性能優化

2009-06-16 16:10:59

Hibernate性能

2020-09-19 21:26:56

webpack

2009-09-08 09:45:23

App Engine性

2022-02-16 14:10:51

服務器性能優化Linux

2024-09-04 14:28:20

Python代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品视频久久久久久 | 欧美一级二级视频 | 狠狠干网| 涩涩片影院 | 色综合激情 | 午夜影院在线播放 | 国产精品看片 | 亚洲福利一区 | 草草视频在线免费观看 | 亚洲一区二区在线播放 | 中文字幕视频一区二区 | chengrenzaixian| 国产高清在线精品一区二区三区 | 亚洲欧美在线一区 | 久草在线影 | 日本天堂视频在线观看 | 国产99久久精品一区二区永久免费 | 嫩草视频在线 | 久久精品国产清自在天天线 | 国产欧美精品一区 | 亚洲九九色 | a级片www| 欧美成人精品 | 免费在线观看一区二区三区 | 欧美精品一区在线发布 | 欧美在线一区二区三区 | 91久久国产综合久久 | 中文字幕av一区 | 久久综合狠狠综合久久 | 国产黄色大片 | 成人激情视频 | 激情久久网 | 欧美日韩亚洲一区 | 视频一区二区三区中文字幕 | 精品区| 色综合成人网 | 国产成人免费在线观看 | 日本涩涩视频 | 亚洲一区二区高清 | 国产精品毛片一区二区三区 | 久久成人av电影 |