




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
程序優化那些事兒一、程序優化概述二、一個典型的優化范例三、程序性能分析四、程序框架優化四、程序邏輯優化五、代碼優化技巧六、編譯器優化七、程序優化實施步驟內容一覽程序優化: 運用各種方法、技巧對現有的代碼重新進行編排、調整,以達到更高的運行性能。程序優化的目標: 提高運行速度
降低資源消耗(程序體積,內存占用、cpu、進程數、句柄等)下面介紹一個優化的例子,有圖有真相概述一個例子目標:把彩色相片轉成黑白相片公式:Y=0.299*R+0.587*G+0.114*B一個例子優化結果機型普通去浮點去除法查表展開循環性能提高嵌入式s12045302199%筆記本ms441280060240941090%臺式機ms36562360123465657984%決定程序運行性能的因素: 硬件平臺 軟件平臺 程序架構 程序邏輯 算法與數據結構 代碼編寫技巧 編譯器性能分析1.硬件平臺:cpu的架構、頻率,內存大小等 監控采用多個多核x86cpu代替sparc,內存也提高到4G,以解決300個節點的性能問題。 不同架構的CPU,其特點也不相同,根據應用需求選擇。2.軟件平臺:操作系統、數據庫、第三方庫、JVM 相同硬件下,cosmos在solaris9上比solaris10上效率更高,在debian4上比在debian5上更少占cpu,和操作系統內核設計有關系。平臺優化1.程序架構優化重新調整程序的架構,消除不合理的架構設計引起的程序性能瓶頸。2.程序邏輯優化在仔細分析業務邏輯的前提下,尋求更合理、更簡單、更高效的程序處理邏輯,以提高程序處理性能。3.代碼優化使用各種代碼編寫技巧,按照編譯器優化的方法和處理器執行指令的特點,對已有正確代碼重新安排、調整,以獲得更好的性能
程序優化的三個層次程序架構優化程序架構:輪詢/觸發、多線程/單線程、共享內存/管道、同步/異步
優點:能夠從根本上解決性能問題
缺點:改動大,成本高,并且可能造成程序的不穩定61850服務器端處理報告的方式:
sisco默認的是定期向裝置讀取所有報告中配置的數據,掃描周期可以配置。掃描周期長了,數據上送的慢;短了,cpu受不了。
咱們裝置可以主動上送變化數據,后來改成觸發模式,上送速度快且cpu占用低。61850客戶端下發請求的方式:
采用異步請求方式,在等待請求返回的時候不耽誤其他工作程序邏輯優化邏輯優化一般只涉及到模塊內的功能的調整,對程序整體影響較小,且往往能同時提高運行速度、減小程序體積、提高程序的可維護性。1.去除程序中無用的邏輯處理,去除cosmos初始化過程中的getalldatavalue過程2.根據業務特點,舍棄部分通用性和模塊性asn1固定長度的編碼asn1_parse函數3.按照業務邏輯流程定制程序流程gsv_on_recved_gooseMessage4.合并同類數據的處理,減少程序執行次數如客戶端處理報告的方法,緩存零散報告,統一處理;如客戶端調定值的處理,一次下發多個定值請求1.代碼優化一般只對代碼進行的較小規模的修改,大多數情況下只針對熱點函數進行。2.了解一些代碼優化技巧,養成習慣,在不影響可讀性的前提下編寫普遍高效的代碼。3.代碼優化往往對程序的其他方面造成影響,如可讀性、模塊性等,要慎重使用。代碼優化-概述代碼優化-降低運算的強度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編譯器的乘除運算均是調用子程序來完成,代碼長、執行速度慢。代碼優化-降低運算的強度2.用加法代替乘法
for(i=0;i<MAX;i++)h=14*i;for(i=h=0;i<MAX;i++)h+=14;3.合并除法以減少除法的次數doublex=a/b/c;優化成doublex=a/(b*c)doublex=a/b+c/b;優化成doublex=(a+c)/b代碼優化-降低運算的強度4.如果被除數比除數大的倍數不多,可以用減法代替除法。intx=200; inty=70; inta=x/y; intb=x%y; 優化后: intx1=200; inty1=70; inta1=0; intb1=x; while(b1>=y1){ b1-=y1; a1++; }代碼優化-降低運算的強度5.用乘法代替除法
doublex=a/b;doubley=c/b;優化后:doubletmp=1/b;doublex=a*tmp;doubley=b*tmp6.在誤差允許的情況下,采用近似計算除法比如顏色處理時,uint8color=a/255;優化成uint8color=a/256即a>>8。代碼優化-降低運算的強度6.整數代替浮點數7.按需選擇賦值符號a=a+1要寫為a++;
a=a+b要寫為a+=b,后者生成的匯編指令更少8.查表法彩圖轉換黑白圖的例子 如果表很大,不好寫,就寫一個init函數,在循環外臨時生成表格。 如果怕初始化時間太長,或者用到的點比較少且比較固定,可以在用到的時候再計算,存到表里。代碼優化-函數1.使用宏定義代替函數定義#defineasn1_GetBOOL(pdata,punit,value)\{\value=pdata[(punit)->offset]&0x01;\}優點:避免函數調用帶來的開銷:傳遞參數的開銷和保存當前程序上下文信息所花費的開銷,函數越復雜需要花費的開銷就越大缺點:1.使用這種方法在優化程序速度的同時,卻增加了內存的開銷,因為在每個應用宏的地方宏都會展開;2.無法跟蹤調試;3.宏可讀性比較差,容易出現問題代碼優化-函數2.減少函數的參數個數,把多個參數合成一個結構體,或者使用全局變量代替,傳遞的參數越多開銷越大3.用合適參數傳遞方法,數據結構等體積較大的參數,傳遞指針4.不需要返回值時,聲明返回值為void代碼優化-if判斷If判斷的特點: 1.從左到右對表達式求值; 2當結果確定后就不再計算其他表達式的值1.把計算速度快的表達式放到左邊:if(strlen(a)>100||b>10)改為if(b>10||strlen(a)>100)2.把概率大的放到左邊:if(a>100||b>0)改為if(b>0||a>100)代碼優化-if判斷3.Ifelse語句和switch中,把最常出現的判斷放在前面示例見code_opt工程switch.cpp4.變換表達式,通過代數恒等式代替復雜操作if(!a&&!b)改為if(!(a||b)),可以少一次!操作;用if(a<b)代替if(sqrt(a)<sqrt(b))代碼優化-循環1循環展開,減少維護循環所有做的工作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代碼優化-循環2.循環合并,把多個對相同一組元素進行操作的循環合并到一起示例見code_opt.cpp3.循環中找到相應的值后就停止循環while((i++)<1000){ if(i==100){ do_something();
break; } }代碼優化-循環4.把循環中不變的判斷拿到循環外面 如果循環過程中,判斷的條件不會變,就把它拿到循環外,從而避免在循環中進行判斷示例見code_opt.cpp代碼優化-循環5.盡可能減少在循環內部做的工作
編寫高效循環的關鍵在于盡可能減少循環內部所做的工作,如果可以在循環外面完成某語句或某個運算,而在循環內只是使用計算結果,就把它放到循環外面For(inti=0;i<count;i++) A=b->c->d->e*(75.5/23)*rate[i];優化成:Tmp=75.5/23;E_tmp=b->c->d->e;For(inti=0;i<count;i++) A=e_tmp*tmp*rate[i];減少了三次指針解引用和一個除法運算的時間代碼優化-循環6.循環嵌套時,把最忙的循環放到最內層,可以減少總循環的次數
for(column=0;column<100;column++)for(row=0;row<5;row++) sum=sum+table[row][column]; 里面的循環執行5*100次,外面的循環執行100次,共600次,把外層循環拿到內層后,外層是5次循環,內層是100*5次,共505次,節省了(600-505)/600即16%的時間。代碼優化-緩存利用緩存機制提高程序性能1.使用緩存提高訪問速度:如cpu的高速緩存機制2.減少函數調用:如報告接收處理,把多個報告的結果進行緩存,通過一次回調給上層。3.防止數據丟失:如網卡驅動中的緩存和61850服務器中的緩存報告4.減少運算次數:緩存需要大量計算的值,如查表法代碼優化-編譯期初始化發現程序中可能存在的運算結果不變的表達式,使用事先計算好的值代替
比如在計算以2為底的函數中
UnsignedintLog2(unsignedintx) { Return(unsignedint)(log(x)/log(2)); } 其中log(2)是個常量,事先計算好替代,減少一次log()調用代碼優化-系統函數注意耗時的系統函數,根據實際需求選擇合適的系統函數 如上一個例子,log()函數是系統提供的函數,為了滿足絕大多數應用,它的精度很高,內部還會把你傳入的整數轉成double處理,而我們只需要返回一個整數,因此log()對我們來書是大材小用,因此改成如下UnsignedintLog2(unsignedintx){ if(x<2)return0; if(x<4)return1; if(x<8)return2; if(x<16)return3; .... if(x<2147483648)return30;} 這個函數只用到了整數,根本沒有浮點的計算,性能得到大幅優化。代碼優化-系統函數 另一種簡化寫法,能適應更多位的情形,32位、64位等UnsignedintLog2(unsignedintx){ Unsignedinti=0; While((x=(x>>1))!=0) i++; Retruni;}代碼優化-數據結構1.選用夠用的類型,減少空間浪費但是哪種效率最高是由cpu決定的,比如charshortint對armv6的效率是一樣的2.使用聯合體節約內存3.使用正確的變量類型,避免沒必要的強制類型轉換;代碼優化-數據結構4.巧用字節對齊的原則節省內存
為了提高數據存取效率,編譯器默認會對結構體(包括其他地方的變量)進行處理,讓寬度為2的基本數據類型(short等)都位于能被2整除的地址上,讓寬度為4的基本數據類型(int等)都位于能被4整除的地址上,以此類推。這樣,兩個數中間就可能需要加入填充字節,所以整個結構體的sizeof值就增長了。示例見code_opt.cpp修改編譯器設置可以指定對齊字節數,添加#pragmapack(4)或修改VC6的工程設置。代碼優化-動態內存動態內存申請的問題:1.效率低,在堆上申請內存需要很多時間2.產生較多內存碎片,系統性能越來越低,最終可能導致系統崩潰3.忘記釋放,導致內存泄露4.可能分配失敗,導致程序異常。代碼優化-動態內存如何減少動態內存申請1.事先估算所有內存需求,初始化時提前申請,一直用下去Iec61850v2中的動態內存優化例子,mvl61850_rpt.c2.使用實變量代替動態申請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.使用內存池模式代碼優化-其他使用匯編重寫熱點函數,一般能提高30%以上的性能示例gsmv中asn1_parse.asm文件使用編譯器優化選項優化,根據程序性能低下的特點選用相關的優化選項使用宏定義,在編譯期屏蔽不同平臺下不需要的功能提高關鍵進程的優先級選用高性能的算法示例排序算法,見qsort工程代碼優化總結代碼優化不是解決性能問題的唯一法寶,1.從實施效果看,完善框架設計、調整程序邏輯設計、選擇更好的算法常常能帶來更大幅度的性能提升2.從實施過程看,提高硬件規格或者合理設置編譯器優化選項會更方便選擇合適的足夠精度的測量方法,找出真正影響性能的地方,并且每次修改完測試修改效果代碼優化需要反復嘗試,這樣才能得到理想的性能提高不同的編譯器和運行環境對同樣的優化方法的性能提升是不一樣的為性能優化工作做好準備的最佳方式是初期編寫清晰易懂的代碼,從而后期方便代碼的理解和修改幾個導致性能低下的原因編碼時容錯方面的考慮為提高程序的容錯性,假設輸入不可靠,可能導致每層接口對同樣的輸入都做嚴格的檢測及錯誤處理,致使性能受損。代碼模塊化的設計模塊化的設計提高了軟件的可維護性和可擴展性,但如果設計不當,模塊間的接口與通信可能產生性能瓶頸。需求的變化為滿足新的需求,程序員不斷的修改代碼,而老的需求不存在時,一般也不會去除相關無用的代碼;更改代碼時往往考慮的是如何使改動最小而不是最合理,時間久了,程序中冗余代碼增多,程序邏輯也越來越混亂,性能自然降低。兼容性的需要設計接口時,為了兼容老的版本或者滿足更多應用的場景,過多的考慮了實現的兼容性、通用性,導致接口邏輯復雜,判斷分支過多,很多實際上用不到的特性增加了程序的開銷何時開始優化1.性能優化開始的越早越好。軟件設計階段就考慮了性能的問題,將來的改動就較少,越到后期改動的成本會越高問題:過早的考慮了代碼的優化,追求代碼性能的高效,而在實際運行過程中,其實只有很少一部分熱點函數需要優化,結果對可讀性、擴展性帶來損害。何時開始優化2.待軟件功能開發完成后再來考慮優化的事,功能都沒做好,優化有什么用呢,防止做太多無用功問題:實現功能時,沒有從程序的邏輯、算法等方面沒有考慮性能問題,導致后期僅僅優化熱點函數仍然無法滿足要求,不得不大動干戈修改程序邏輯和算法甚至架構,造成損失更大何時開始優化正確的方法:1.在需求階段,就要把性能指標定義下來2.在軟件設計階段,根據這些指標考量程序邏輯和算法3.軟件功能基本完成后,測試性能,對邏輯做細微調整,查找熱點函數,進行代碼優化優化的步驟根據實際需求,確定性能指標,給出一個合適的評價性能的標準:理想值,下限值。進行優化之前,一定考慮清楚性能指標是合理且必須的測試程序當前的狀況,離目標還有多遠,做到心中有數分析程序,查找性能瓶頸,一般來講20%的代碼占用的80%的時間修改程序。程序優化應優先優化程序邏輯,然后才是代碼級別的優化。測試,驗證優化后的結果如果滿足要求,就停止優化。否則回到3。防止過度優化,可能會降低代碼可讀性,浪費時間精力。性能分析性能低下的表現:1.程序的運算量很大,導致cpu過于繁忙2.程序需要做大量的I/O操作,讀寫文件、網絡等,cpu更多的是等待3.程序直接互相等待,cpu利用低,但程序依然運行緩慢查找性能瓶頸的方法:1.根據程序表現,分析程序流程,走讀代碼2.在程序中添加日志,記錄時標及相關信息3.使用性能分析工具,如linux下有top、gprof和OProfile等,windows下有aqtime等編譯器-概述主流的C/C++編譯器:MS的CL、GNU的gcc、Intel的icl、Codegear的bcc。衡量編譯的標準:編譯速度、對標準的支持度、目標程序的性能、支持的平臺、編譯器的體積、易用性編譯器的選擇在大部分平臺上,gcc是C/C++編譯器的首選,對C/C++標準的支持也是最完善的。intel的編譯器針對
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年低溫超導材料資金申請報告代可行性研究報告
- 能源政策對環境的影響試題及答案
- 如何保證公共政策的有效執行試題及答案
- 突破網絡工程師考試難題試題及答案
- 環境政策中的公眾參與案例探討試題及答案
- 解析西方政治制度中的法治問題試題及答案
- 政治權力與社會結構的關系試題及答案
- 西方國家教育公平與社會經濟試題及答案
- 民主制度與非民主制度的比較分析試題及答案
- 西方歷史事件對政治制度的影響試題及答案
- 體育與健康人教六年級全一冊實心球教案
- TSG-R0005-2022《移動式壓力容器安全技術監察規程》(2022版)
- 配電室維保方案資料
- 汽車4S店老客戶關懷活動方案
- 非相干散射雷達調研報告
- 醫院崗位設置與人員編制標準
- 原油管道工程動火連頭安全技術方案
- 土石方場地平整施工組織方案
- 外周血單個核細胞分離方法探討
- LED亮度自動調節系統設計
- SD7V16可變排量汽車空調壓縮機_圖文
評論
0/150
提交評論