偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

[[339022]]

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

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

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

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

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

目標

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

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

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

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

top

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

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

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

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

系統(tǒng)中可能沒有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)//生成隨機數(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í)行程序并運行:

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

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

打開另外一個終端,執(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命令用于獲取指定程序名的進程ID。

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

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

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

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

執(zhí)行上面的命令一段時間,用于采集相關性能和符號信息,隨后ctrl+c中止。默認當前目錄下生成perf.data,不過這里面的數(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信息。

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

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

  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 

這樣看也是非常清晰的。

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

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

總結

 

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

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

 

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

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)化開發(fā)

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

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

2025-06-03 00:00:06

性能優(yōu)化性能指標響應時間

2021-05-17 11:55:48

監(jiān)控命令Linux

2021-03-16 10:20:56

監(jiān)控系統(tǒng)架構技術

2021-05-10 08:08:25

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

2011-05-03 10:17:25

CSS

2013-06-09 15:31:35

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

2020-09-19 21:26:56

webpack

2017-08-08 09:45:43

Python性能優(yōu)化

2009-06-16 16:10:59

Hibernate性能

2022-02-16 14:10:51

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

2009-09-08 09:45:23

App Engine性

2024-09-04 14:28:20

Python代碼
點贊
收藏

51CTO技術棧公眾號