您好,登錄后才能下訂單哦!
這篇文章主要介紹了linux中為什么要性能優化,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
為什么要性能優化
也許是想要支持更高的吞吐量,想要更小的延遲,或者提高資源的利用率等,這些都是性能優化的目標之一。不過需要提醒的是,不要過早的進行性能優化。如果當前并沒有任何性能問題,又何必耗費這個精力呢?當前一些有助于提高性能的編碼習慣還是可以時刻保持的。
目標
全面的性能優化不是一件簡單的事情。本系列文章不在于介紹性能優化原理或者特定的算法優化。旨在分享一些實踐中常用到的技巧,同時也主要關注CPU方面。
如何發現性能瓶頸
解決性能問題的第一步是發現性能問題。如何快速發現性能問題呢?對于本文來說,如何發現那些使CPU不停地瞎忙的代碼呢?為什么這里是說讓CPU瞎忙的代碼?
舉個例子,完成某個事情,你可能只需要一個CPU時間片,但是由于代碼不夠好,使得仍然需要多個CPU時間片。導致CPU非常忙碌,而無法繼續提高它的效率。
top
這個命令相信大家都用過,可以實時看到進程的一些狀態。它的使用方法有很多文章不厭其煩地對其進行了介紹,本文不打算進行介紹。我們可以通過top命令看到某個進程占用的CPU,但是CPU占用高并不代表它有性能問題,也有可能是CPU正在有效地高速運轉,并沒有占著茅坑不拉屎。
快速發現
想必我們都聽過八二法則,同樣的,80%的性能問題集中于20%的代碼。因此我們只要找到這20%的部分代碼,就可以有效地解決一些性能問題。
本文使用perf命令,它很強大,支持的參數也非常多,不過沒關系,本文也沒打算全部介紹。
系統中可能沒有perf命令,ubuntu可以使用如下方法安裝:
sudo apt install linux-tools-common
實例
直接來看示例吧。例子很簡單,只是將字符串的字母轉為大寫罷了。當然了,很多人可能一眼就看出了哪里有性能問題,不過沒關系,這個例子只是為了說明perf的應用。
//toUpper.c #include<stdlib.h> #include<stdio.h> #include<time.h> #include<ctype.h> #include<string.h> #include<sys/time.h> #define MAX_LEN 1024*1024 void printCostTime(struct timeval *start,struct timeval *end) { if(NULL == start || NULL == end) { return; } long cost = (end->tv_sec - start->tv_sec) * 1000 + (end->tv_usec - start->tv_usec)/1000; printf("cost time: %ld ms\n",cost); } int main(void) { srand(time(NULL)); int min = 'a'; int max = 'z'; char *str = malloc(MAX_LEN); //申請失敗則退出 if(NULL == str) { printf("failed\n"); return -1; } unsigned int i = 0; while(i < MAX_LEN)//生成隨機數 { str[i] = ( rand() % ( max - min ) ) + min; i++; } str[MAX_LEN - 1] = 0; struct timeval start,end; gettimeofday(&start,NULL); for(i = 0;i < strlen(str) ;i++) { str[i] = toupper( str[i] ); } gettimeofday(&end,NULL); printCostTime(&start,&end); free(str); str = NULL; return 0; }
編譯成可執行程序并運行:
$ gcc -o toUpper toUpper.c $ ./toUpper
這個時候我們用top查看結果發現toUpper程序占用CPU 100%:
$ top -p `pidof toUpper` PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 24456 root 20 0 5248 2044 952 R 100.0 0.0 0:07.13 toUpper
打開另外一個終端,執行命令:
$ perf top -p `pidof toUpper` Samples: 1K of event 'cycles:ppp', Event count (approx.): 657599945 Overhead Shared Object Symbol 99.13% libc-2.23.so [.] strlen 0.19% [kernel] [k] perf_event_task_tick 0.11% [kernel] [k] prepare_exit_to_usermode 0.10% libc-2.23.so [.] toupper 0.09% [kernel] [k] rcu_check_callbacks 0.09% [kernel] [k] reweight_entity 0.09% [kernel] [k] task_tick_fair 0.09% [kernel] [k] native_write_msr 0.09% [kernel] [k] trigger_load_balance 0.00% [kernel] [k] native_apic_mem_write 0.00% [kernel] [k] __perf_event_enable 0.00% [kernel] [k] intel_bts_enable_local
其中pidof命令用于獲取指定程序名的進程ID。
看到結果了嗎?可以很清楚地看到,strlen函數占用了整個程序99%的CPU,那這個CPU的占用是否可以優化掉呢?我們現在都清楚,顯然是可以的,在對每一個字符串進行大寫轉換時,都進行了字符串長度的計算,顯然是沒有必要,可以拿到循環之外的。
同時我們也關注到,這里面有很多符號可能完全沒見過,不知道什么含義了,比例如reweight_entity,不過我們知道它前面有著kernel字樣,因此也就明白,這是內核干的事情,僅此而已。
這里實時查看的方法,當然你也可以保存信息進行查看。
$ perf record -e cycles -p `pidof toUpper` -g -a
執行上面的命令一段時間,用于采集相關性能和符號信息,隨后ctrl+c中止。默認當前目錄下生成perf.data,不過這里面的數據不易閱讀,因此執行:
$ perf report + 100.00% 0.00% toUpper [unknown] [k] 0x03ee258d4c544155 + 100.00% 0.00% toUpper libc-2.23.so [.] __libc_start_main + 99.72% 99.34% toUpper libc-2.23.so [.] strlen 0.21% 0.02% toUpper [kernel.kallsyms] [k] apic_timer_interrupt 0.19% 0.00% toUpper [kernel.kallsyms] [k] smp_apic_timer_interrupt 0.16% 0.00% toUpper [kernel.kallsyms] [k] ret_from_intr 0.16% 0.00% toUpper [kernel.kallsyms] [k] hrtimer_interrupt 0.16% 0.00% toUpper [kernel.kallsyms] [k] do_IRQ 0.15% 0.15% toUpper libc-2.23.so [.] toupper 0.15% 0.00% toUpper [kernel.kallsyms] [k] handle_irq 0.15% 0.00% toUpper [kernel.kallsyms] [k] handle_edge_irq 0.15% 0.00% toUpper [kernel.kallsyms] [k] handle_irq_event 0.15% 0.00% toUpper [kernel.kallsyms] [k] handle_irq_event_percpu 0.14% 0.00% toUpper [kernel.kallsyms] [k] __handle_irq_event_percpu 0.14% 0.01% toUpper [kernel.kallsyms] [k] __hrtimer_run_queues 0.13% 0.00% toUpper [kernel.kallsyms] [k] _rtl_pci_interrupt
其中-g參數為了保存調用調用鏈,-a表示保存所有CPU信息。
因此就可以看到采樣信息了,怎么樣是不是很明顯,其中的+部分還可以展開,看到調用鏈。
例如展開的部分信息如下:
- 100.00% 0.00% toUpper libc-2.23.so [.] __libc_start_main - __libc_start_main 99.72% strlen
當然了,實際上你也可以將結果重定向到另外一個文件,便于查看:
$ perf report > result $ more result # Event count (approx.): 23881569776 # # Children Self Command Shared Object Symbol # ........ ........ ....... ................. .............................. ................... # 100.00% 0.00% toUpper [unknown] [k] 0x03ee258d4c544155 | ---0x3ee258d4c544155 __libc_start_main | --99.72%--strlen 100.00% 0.00% toUpper libc-2.23.so [.] __libc_start_main | ---__libc_start_main | --99.72%--strlen 99.72% 99.34% toUpper libc-2.23.so [.] strlen | --99.34%--0x3ee258d4c544155
感謝你能夠認真閱讀完這篇文章,希望小編分享的“linux中為什么要性能優化”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。