溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

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

發(fā)布時(shí)間:2021-10-25 10:36:20 來(lái)源:億速云 閱讀:199 作者:小新 欄目:系統(tǒng)運(yùn)維

這篇文章主要介紹了linux中為什么要性能優(yōu)化,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

為什么要性能優(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可以使用如下方法安裝:

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)用。

 //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);     //申請(qǐng)失敗則退出     if(NULL == str)     {         printf("failed\n");         return -1;     }     unsigned int i = 0;     while(i < MAX_LEN)//生成隨機(jī)數(shù)     {         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; }

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

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

這個(gè)時(shí)候我們用top查看結(jié)果發(fā)現(xiàn)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

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

$ 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命令用于獲取指定程序名的進(jìn)程ID。

看到結(jié)果了嗎?可以很清楚地看到,strlen函數(shù)占用了整個(gè)程序99%的CPU,那這個(gè)CPU的占用是否可以?xún)?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)行查看。

$ 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í)行:

$ 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參數(shù)為了保存調(diào)用調(diào)用鏈,-a表示保存所有CPU信息。

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

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

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

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

$ 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

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“l(fā)inux中為什么要性能優(yōu)化”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI