程序優(yōu)化那些事兒_第1頁
程序優(yōu)化那些事兒_第2頁
程序優(yōu)化那些事兒_第3頁
程序優(yōu)化那些事兒_第4頁
程序優(yōu)化那些事兒_第5頁
已閱讀5頁,還剩42頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

程序優(yōu)化那些事兒一、程序優(yōu)化概述二、一個典型的優(yōu)化范例三、程序性能分析四、程序框架優(yōu)化四、程序邏輯優(yōu)化五、代碼優(yōu)化技巧六、編譯器優(yōu)化七、程序優(yōu)化實施步驟內(nèi)容一覽程序優(yōu)化: 運用各種方法、技巧對現(xiàn)有的代碼重新進行編排、調(diào)整,以達到更高的運行性能。程序優(yōu)化的目標(biāo): 提高運行速度

降低資源消耗(程序體積,內(nèi)存占用、cpu、進程數(shù)、句柄等)下面介紹一個優(yōu)化的例子,有圖有真相概述一個例子目標(biāo):把彩色相片轉(zhuǎn)成黑白相片公式:Y=0.299*R+0.587*G+0.114*B一個例子優(yōu)化結(jié)果機型普通去浮點去除法查表展開循環(huán)性能提高嵌入式s12045302199%筆記本ms441280060240941090%臺式機ms36562360123465657984%決定程序運行性能的因素: 硬件平臺 軟件平臺 程序架構(gòu) 程序邏輯 算法與數(shù)據(jù)結(jié)構(gòu) 代碼編寫技巧 編譯器性能分析1.硬件平臺:cpu的架構(gòu)、頻率,內(nèi)存大小等 監(jiān)控采用多個多核x86cpu代替sparc,內(nèi)存也提高到4G,以解決300個節(jié)點的性能問題。 不同架構(gòu)的CPU,其特點也不相同,根據(jù)應(yīng)用需求選擇。2.軟件平臺:操作系統(tǒng)、數(shù)據(jù)庫、第三方庫、JVM 相同硬件下,cosmos在solaris9上比solaris10上效率更高,在debian4上比在debian5上更少占cpu,和操作系統(tǒng)內(nèi)核設(shè)計有關(guān)系。平臺優(yōu)化1.程序架構(gòu)優(yōu)化重新調(diào)整程序的架構(gòu),消除不合理的架構(gòu)設(shè)計引起的程序性能瓶頸。2.程序邏輯優(yōu)化在仔細分析業(yè)務(wù)邏輯的前提下,尋求更合理、更簡單、更高效的程序處理邏輯,以提高程序處理性能。3.代碼優(yōu)化使用各種代碼編寫技巧,按照編譯器優(yōu)化的方法和處理器執(zhí)行指令的特點,對已有正確代碼重新安排、調(diào)整,以獲得更好的性能

程序優(yōu)化的三個層次程序架構(gòu)優(yōu)化程序架構(gòu):輪詢/觸發(fā)、多線程/單線程、共享內(nèi)存/管道、同步/異步

優(yōu)點:能夠從根本上解決性能問題

缺點:改動大,成本高,并且可能造成程序的不穩(wěn)定61850服務(wù)器端處理報告的方式:

sisco默認的是定期向裝置讀取所有報告中配置的數(shù)據(jù),掃描周期可以配置。掃描周期長了,數(shù)據(jù)上送的慢;短了,cpu受不了。

咱們裝置可以主動上送變化數(shù)據(jù),后來改成觸發(fā)模式,上送速度快且cpu占用低。61850客戶端下發(fā)請求的方式:

采用異步請求方式,在等待請求返回的時候不耽誤其他工作程序邏輯優(yōu)化邏輯優(yōu)化一般只涉及到模塊內(nèi)的功能的調(diào)整,對程序整體影響較小,且往往能同時提高運行速度、減小程序體積、提高程序的可維護性。1.去除程序中無用的邏輯處理,去除cosmos初始化過程中的getalldatavalue過程2.根據(jù)業(yè)務(wù)特點,舍棄部分通用性和模塊性asn1固定長度的編碼asn1_parse函數(shù)3.按照業(yè)務(wù)邏輯流程定制程序流程gsv_on_recved_gooseMessage4.合并同類數(shù)據(jù)的處理,減少程序執(zhí)行次數(shù)如客戶端處理報告的方法,緩存零散報告,統(tǒng)一處理;如客戶端調(diào)定值的處理,一次下發(fā)多個定值請求1.代碼優(yōu)化一般只對代碼進行的較小規(guī)模的修改,大多數(shù)情況下只針對熱點函數(shù)進行。2.了解一些代碼優(yōu)化技巧,養(yǎng)成習(xí)慣,在不影響可讀性的前提下編寫普遍高效的代碼。3.代碼優(yōu)化往往對程序的其他方面造成影響,如可讀性、模塊性等,要慎重使用。代碼優(yōu)化-概述代碼優(yōu)化-降低運算的強度1.用移位操作代替乘除法

a=b/8;改為:a=b>>3;a=a*8;改為:a=b<<3;a=b%8;改為:a=b&7;a=a*9;改為:a=b<<3+b 位操作只需一個指令周期即可完成,而大部分的C編譯器的乘除運算均是調(diào)用子程序來完成,代碼長、執(zhí)行速度慢。代碼優(yōu)化-降低運算的強度2.用加法代替乘法

for(i=0;i<MAX;i++)h=14*i;for(i=h=0;i<MAX;i++)h+=14;3.合并除法以減少除法的次數(shù)doublex=a/b/c;優(yōu)化成doublex=a/(b*c)doublex=a/b+c/b;優(yōu)化成doublex=(a+c)/b代碼優(yōu)化-降低運算的強度4.如果被除數(shù)比除數(shù)大的倍數(shù)不多,可以用減法代替除法。intx=200; inty=70; inta=x/y; intb=x%y; 優(yōu)化后: intx1=200; inty1=70; inta1=0; intb1=x; while(b1>=y1){ b1-=y1; a1++; }代碼優(yōu)化-降低運算的強度5.用乘法代替除法

doublex=a/b;doubley=c/b;優(yōu)化后:doubletmp=1/b;doublex=a*tmp;doubley=b*tmp6.在誤差允許的情況下,采用近似計算除法比如顏色處理時,uint8color=a/255;優(yōu)化成uint8color=a/256即a>>8。代碼優(yōu)化-降低運算的強度6.整數(shù)代替浮點數(shù)7.按需選擇賦值符號a=a+1要寫為a++;

a=a+b要寫為a+=b,后者生成的匯編指令更少8.查表法彩圖轉(zhuǎn)換黑白圖的例子 如果表很大,不好寫,就寫一個init函數(shù),在循環(huán)外臨時生成表格。 如果怕初始化時間太長,或者用到的點比較少且比較固定,可以在用到的時候再計算,存到表里。代碼優(yōu)化-函數(shù)1.使用宏定義代替函數(shù)定義#defineasn1_GetBOOL(pdata,punit,value)\{\value=pdata[(punit)->offset]&0x01;\}優(yōu)點:避免函數(shù)調(diào)用帶來的開銷:傳遞參數(shù)的開銷和保存當(dāng)前程序上下文信息所花費的開銷,函數(shù)越復(fù)雜需要花費的開銷就越大缺點:1.使用這種方法在優(yōu)化程序速度的同時,卻增加了內(nèi)存的開銷,因為在每個應(yīng)用宏的地方宏都會展開;2.無法跟蹤調(diào)試;3.宏可讀性比較差,容易出現(xiàn)問題代碼優(yōu)化-函數(shù)2.減少函數(shù)的參數(shù)個數(shù),把多個參數(shù)合成一個結(jié)構(gòu)體,或者使用全局變量代替,傳遞的參數(shù)越多開銷越大3.用合適參數(shù)傳遞方法,數(shù)據(jù)結(jié)構(gòu)等體積較大的參數(shù),傳遞指針4.不需要返回值時,聲明返回值為void代碼優(yōu)化-if判斷If判斷的特點: 1.從左到右對表達式求值; 2當(dāng)結(jié)果確定后就不再計算其他表達式的值1.把計算速度快的表達式放到左邊:if(strlen(a)>100||b>10)改為if(b>10||strlen(a)>100)2.把概率大的放到左邊:if(a>100||b>0)改為if(b>0||a>100)代碼優(yōu)化-if判斷3.Ifelse語句和switch中,把最常出現(xiàn)的判斷放在前面示例見code_opt工程switch.cpp4.變換表達式,通過代數(shù)恒等式代替復(fù)雜操作if(!a&&!b)改為if(!(a||b)),可以少一次!操作;用if(a<b)代替if(sqrt(a)<sqrt(b))代碼優(yōu)化-循環(huán)1循環(huán)展開,減少維護循環(huán)所有做的工作for(i=0;i<100;i++) do_stuff(i);新代碼:for(i=0;i<100;i+=5){do_stuff(i);do_stuff(i+1);do_stuff(i+2);do_stuff(i+3);do_stuff(i+4);}性能測試見code_opt.cpp代碼優(yōu)化-循環(huán)2.循環(huán)合并,把多個對相同一組元素進行操作的循環(huán)合并到一起示例見code_opt.cpp3.循環(huán)中找到相應(yīng)的值后就停止循環(huán)while((i++)<1000){ if(i==100){ do_something();

break; } }代碼優(yōu)化-循環(huán)4.把循環(huán)中不變的判斷拿到循環(huán)外面 如果循環(huán)過程中,判斷的條件不會變,就把它拿到循環(huán)外,從而避免在循環(huán)中進行判斷示例見code_opt.cpp代碼優(yōu)化-循環(huán)5.盡可能減少在循環(huán)內(nèi)部做的工作

編寫高效循環(huán)的關(guān)鍵在于盡可能減少循環(huán)內(nèi)部所做的工作,如果可以在循環(huán)外面完成某語句或某個運算,而在循環(huán)內(nèi)只是使用計算結(jié)果,就把它放到循環(huán)外面For(inti=0;i<count;i++) A=b->c->d->e*(75.5/23)*rate[i];優(yōu)化成:Tmp=75.5/23;E_tmp=b->c->d->e;For(inti=0;i<count;i++) A=e_tmp*tmp*rate[i];減少了三次指針解引用和一個除法運算的時間代碼優(yōu)化-循環(huán)6.循環(huán)嵌套時,把最忙的循環(huán)放到最內(nèi)層,可以減少總循環(huán)的次數(shù)

for(column=0;column<100;column++)for(row=0;row<5;row++) sum=sum+table[row][column]; 里面的循環(huán)執(zhí)行5*100次,外面的循環(huán)執(zhí)行100次,共600次,把外層循環(huán)拿到內(nèi)層后,外層是5次循環(huán),內(nèi)層是100*5次,共505次,節(jié)省了(600-505)/600即16%的時間。代碼優(yōu)化-緩存利用緩存機制提高程序性能1.使用緩存提高訪問速度:如cpu的高速緩存機制2.減少函數(shù)調(diào)用:如報告接收處理,把多個報告的結(jié)果進行緩存,通過一次回調(diào)給上層。3.防止數(shù)據(jù)丟失:如網(wǎng)卡驅(qū)動中的緩存和61850服務(wù)器中的緩存報告4.減少運算次數(shù):緩存需要大量計算的值,如查表法代碼優(yōu)化-編譯期初始化發(fā)現(xiàn)程序中可能存在的運算結(jié)果不變的表達式,使用事先計算好的值代替

比如在計算以2為底的函數(shù)中

UnsignedintLog2(unsignedintx) { Return(unsignedint)(log(x)/log(2)); } 其中l(wèi)og(2)是個常量,事先計算好替代,減少一次log()調(diào)用代碼優(yōu)化-系統(tǒng)函數(shù)注意耗時的系統(tǒng)函數(shù),根據(jù)實際需求選擇合適的系統(tǒng)函數(shù) 如上一個例子,log()函數(shù)是系統(tǒng)提供的函數(shù),為了滿足絕大多數(shù)應(yīng)用,它的精度很高,內(nèi)部還會把你傳入的整數(shù)轉(zhuǎn)成double處理,而我們只需要返回一個整數(shù),因此log()對我們來書是大材小用,因此改成如下UnsignedintLog2(unsignedintx){ if(x<2)return0; if(x<4)return1; if(x<8)return2; if(x<16)return3; .... if(x<2147483648)return30;} 這個函數(shù)只用到了整數(shù),根本沒有浮點的計算,性能得到大幅優(yōu)化。代碼優(yōu)化-系統(tǒng)函數(shù) 另一種簡化寫法,能適應(yīng)更多位的情形,32位、64位等UnsignedintLog2(unsignedintx){ Unsignedinti=0; While((x=(x>>1))!=0) i++; Retruni;}代碼優(yōu)化-數(shù)據(jù)結(jié)構(gòu)1.選用夠用的類型,減少空間浪費但是哪種效率最高是由cpu決定的,比如charshortint對armv6的效率是一樣的2.使用聯(lián)合體節(jié)約內(nèi)存3.使用正確的變量類型,避免沒必要的強制類型轉(zhuǎn)換;代碼優(yōu)化-數(shù)據(jù)結(jié)構(gòu)4.巧用字節(jié)對齊的原則節(jié)省內(nèi)存

為了提高數(shù)據(jù)存取效率,編譯器默認會對結(jié)構(gòu)體(包括其他地方的變量)進行處理,讓寬度為2的基本數(shù)據(jù)類型(short等)都位于能被2整除的地址上,讓寬度為4的基本數(shù)據(jù)類型(int等)都位于能被4整除的地址上,以此類推。這樣,兩個數(shù)中間就可能需要加入填充字節(jié),所以整個結(jié)構(gòu)體的sizeof值就增長了。示例見code_opt.cpp修改編譯器設(shè)置可以指定對齊字節(jié)數(shù),添加#pragmapack(4)或修改VC6的工程設(shè)置。代碼優(yōu)化-動態(tài)內(nèi)存動態(tài)內(nèi)存申請的問題:1.效率低,在堆上申請內(nèi)存需要很多時間2.產(chǎn)生較多內(nèi)存碎片,系統(tǒng)性能越來越低,最終可能導(dǎo)致系統(tǒng)崩潰3.忘記釋放,導(dǎo)致內(nèi)存泄露4.可能分配失敗,導(dǎo)致程序異常。代碼優(yōu)化-動態(tài)內(nèi)存如何減少動態(tài)內(nèi)存申請1.事先估算所有內(nèi)存需求,初始化時提前申請,一直用下去Iec61850v2中的動態(tài)內(nèi)存優(yōu)化例子,mvl61850_rpt.c2.使用實變量代替動態(tài)申請Char*str=malloc(strlen); 改為 charstr[MAX_LEN];4.多個變量使用一次申請int*a,*b;float*c;double*d a=malloc(sizeof(int)*2+sizeof(float)+sizeof(double); b=a+1; c=(float*)(b+1); d=(double*)(c+1);5.使用內(nèi)存池模式代碼優(yōu)化-其他使用匯編重寫熱點函數(shù),一般能提高30%以上的性能示例gsmv中asn1_parse.asm文件使用編譯器優(yōu)化選項優(yōu)化,根據(jù)程序性能低下的特點選用相關(guān)的優(yōu)化選項使用宏定義,在編譯期屏蔽不同平臺下不需要的功能提高關(guān)鍵進程的優(yōu)先級選用高性能的算法示例排序算法,見qsort工程代碼優(yōu)化總結(jié)代碼優(yōu)化不是解決性能問題的唯一法寶,1.從實施效果看,完善框架設(shè)計、調(diào)整程序邏輯設(shè)計、選擇更好的算法常常能帶來更大幅度的性能提升2.從實施過程看,提高硬件規(guī)格或者合理設(shè)置編譯器優(yōu)化選項會更方便選擇合適的足夠精度的測量方法,找出真正影響性能的地方,并且每次修改完測試修改效果代碼優(yōu)化需要反復(fù)嘗試,這樣才能得到理想的性能提高不同的編譯器和運行環(huán)境對同樣的優(yōu)化方法的性能提升是不一樣的為性能優(yōu)化工作做好準(zhǔn)備的最佳方式是初期編寫清晰易懂的代碼,從而后期方便代碼的理解和修改幾個導(dǎo)致性能低下的原因編碼時容錯方面的考慮為提高程序的容錯性,假設(shè)輸入不可靠,可能導(dǎo)致每層接口對同樣的輸入都做嚴(yán)格的檢測及錯誤處理,致使性能受損。代碼模塊化的設(shè)計模塊化的設(shè)計提高了軟件的可維護性和可擴展性,但如果設(shè)計不當(dāng),模塊間的接口與通信可能產(chǎn)生性能瓶頸。需求的變化為滿足新的需求,程序員不斷的修改代碼,而老的需求不存在時,一般也不會去除相關(guān)無用的代碼;更改代碼時往往考慮的是如何使改動最小而不是最合理,時間久了,程序中冗余代碼增多,程序邏輯也越來越混亂,性能自然降低。兼容性的需要設(shè)計接口時,為了兼容老的版本或者滿足更多應(yīng)用的場景,過多的考慮了實現(xiàn)的兼容性、通用性,導(dǎo)致接口邏輯復(fù)雜,判斷分支過多,很多實際上用不到的特性增加了程序的開銷何時開始優(yōu)化1.性能優(yōu)化開始的越早越好。軟件設(shè)計階段就考慮了性能的問題,將來的改動就較少,越到后期改動的成本會越高問題:過早的考慮了代碼的優(yōu)化,追求代碼性能的高效,而在實際運行過程中,其實只有很少一部分熱點函數(shù)需要優(yōu)化,結(jié)果對可讀性、擴展性帶來損害。何時開始優(yōu)化2.待軟件功能開發(fā)完成后再來考慮優(yōu)化的事,功能都沒做好,優(yōu)化有什么用呢,防止做太多無用功問題:實現(xiàn)功能時,沒有從程序的邏輯、算法等方面沒有考慮性能問題,導(dǎo)致后期僅僅優(yōu)化熱點函數(shù)仍然無法滿足要求,不得不大動干戈修改程序邏輯和算法甚至架構(gòu),造成損失更大何時開始優(yōu)化正確的方法:1.在需求階段,就要把性能指標(biāo)定義下來2.在軟件設(shè)計階段,根據(jù)這些指標(biāo)考量程序邏輯和算法3.軟件功能基本完成后,測試性能,對邏輯做細微調(diào)整,查找熱點函數(shù),進行代碼優(yōu)化優(yōu)化的步驟根據(jù)實際需求,確定性能指標(biāo),給出一個合適的評價性能的標(biāo)準(zhǔn):理想值,下限值。進行優(yōu)化之前,一定考慮清楚性能指標(biāo)是合理且必須的測試程序當(dāng)前的狀況,離目標(biāo)還有多遠,做到心中有數(shù)分析程序,查找性能瓶頸,一般來講20%的代碼占用的80%的時間修改程序。程序優(yōu)化應(yīng)優(yōu)先優(yōu)化程序邏輯,然后才是代碼級別的優(yōu)化。測試,驗證優(yōu)化后的結(jié)果如果滿足要求,就停止優(yōu)化。否則回到3。防止過度優(yōu)化,可能會降低代碼可讀性,浪費時間精力。性能分析性能低下的表現(xiàn):1.程序的運算量很大,導(dǎo)致cpu過于繁忙2.程序需要做大量的I/O操作,讀寫文件、網(wǎng)絡(luò)等,cpu更多的是等待3.程序直接互相等待,cpu利用低,但程序依然運行緩慢查找性能瓶頸的方法:1.根據(jù)程序表現(xiàn),分析程序流程,走讀代碼2.在程序中添加日志,記錄時標(biāo)及相關(guān)信息3.使用性能分析工具,如linux下有top、gprof和OProfile等,windows下有aqtime等編譯器-概述主流的C/C++編譯器:MS的CL、GNU的gcc、Intel的icl、Codegear的bcc。衡量編譯的標(biāo)準(zhǔn):編譯速度、對標(biāo)準(zhǔn)的支持度、目標(biāo)程序的性能、支持的平臺、編譯器的體積、易用性編譯器的選擇在大部分平臺上,gcc是C/C++編譯器的首選,對C/C++標(biāo)準(zhǔn)的支持也是最完善的。intel的編譯器針對

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論