C++性能優化實踐

優化準則:
1. 二八法則:在任何一組東西中,最重要的只占其中一小部分,約20%,其余80%的盡管是多數,卻是次要的;在優化實踐中,我們將精力集中在優化那20%最耗時的代碼上,整體性能將有顯著的提升; 這個很好理解。函數A雖然代碼量大,但在一次正常執行流程中,只調用了一次。而另一個函數B代碼量比A小很多,但被調用了1000次。顯然,我們更應關註B的優化。
2. 編完代碼,再優化;編碼的時候總是考慮最佳性能未必總是好的;在強調最佳性能的編碼方式的同時,可能就損失了代碼的可讀性和開發效率;
工具:
1 Gprof
工欲善其事,必先利其器。對於Linux平臺下C++的優化,我們使用gprof工具。 gprof是GNU profile工具,可以運行於linux、AIX、Sun等操作系統進行C、C++、Pascal、Fortran程序的性能分析,用於程序的性能優化以及程序瓶頸問題的查找和解決。通過分析應用程序運行時產生的“flat profile”,可以得到每個函數的調用次數,消耗的CPU時間(只統計CPU時間,對IO瓶頸無能為力),也可以得到函數的“調用關系圖”,包括函數調用的層次關系,每個函數調用花費了多少時間。
2. gprof使用步驟
1)    用gcc、g++、xlC編譯程序時,使用-pg參數,如:g++ -pg -o test.exe test.cpp 編譯器會自動在目標代碼中插入用於性能測試的代碼片斷,這些代碼在程序運行時采集並記錄函數的調用關系和調用次數,並記錄函數自身執行時間和被調用函數的執行時間。
2)    執行編譯後的可執行程序,如:./test.exe。該步驟運行程序的時間會稍慢於正常編譯的可執行程序的運行時間。程序運行結束後,會在程序所在路徑下生成一個缺省文件名為gmon.out的文件,這個文件就是記錄程序運行的性能、調用關系、調用次數等信息的數據文件。
3)    使用gprof命令來分析記錄程序運行信息的gmon.out文件,如:gprof test.exe gmon.out則可以在顯示器上看到函數調用相關的統計、分析信息。 上述信息也可以采用gprof test.exe gmon.out> gprofresult.txt重定向到文本文件以便於後續分析。


以上只是gpro的使用步驟簡介,關於gprof使用實例詳見附錄1;
實踐
我們的程序遇到了性能瓶頸,在采用架構改造,改用內存數據庫之前,我們考慮從代碼級入手,先嘗試代碼級的優化; 通過使用gprof分析,我們發現以下2個最為突出的問題:
1.初始化大對象耗時
分析報告:307   6.5% VOBJ1::VOBJ1@240038 VOBJ1
在整個執行流程中被調用307次,其對象初始化耗時占到6.5%。
這個對象很大,包含的屬性多,屬於基礎數據結構;
在程序進入構造函數函數體之前,類的父類對象和所有子成員變量對象已經被生成和構造。如果在構造函數體內位其執行賦值操作,顯示屬於浪費。如果在構造函數時已經知道如何為類的子成員變量初始化,那麽應該將這些初始化信息通過構造函數的初始化列表賦予子成員變量,而不是在構造函數函數體中進行這些初始化。因為進入構造函數函數體之前,這些子成員變量已經初始化過一次了。
在C++程序中,創建/銷毀對象是影響性能的一個非常突出的操作。首先,如果是從全局堆中生成對象,則需要首先進行動態內存分配操作。眾所周知,動態分配/回收在C/C++程序中一直都是非常耗時的。因為牽涉到尋找匹配大小的內存塊,找到後可能還需要截斷處理,然後還需要修改維護全局堆內存使用情況信息的鏈表等。
解決方法:我們將大部分的初始化操作都移到初始化列表中,性能消耗降到1.8%。
2.Map使用不當
分析報告:89   6.8% Recordset::GetField
Recordset的getField被調用了89次,性能消耗占到6.8%;

Recordset是我們在在數據庫層面的包裝,對應取出數據的記錄集;(用過ADO的朋友很熟悉); 由於我們使用的是底層c++數據庫接口,通過對數據庫原始api進行一層包裝,從而屏蔽開發人員對底層api的直接操作。 這樣的包裝,帶來的好處就是不用直接與底層數據庫交互,在代碼編寫方面方便不少,代碼可讀性也很好;帶來的問題就是性能的損失;


C++性能優化實踐

C++性能优化 指南(强列推荐) chm版 Part I: Everything But the Code Chapter 1. Optimizing: What Is It All About? Performance Footprint Summary Chapter 2. Creating a New System System Requirements System Design Issues The Development Process Data Processing Methods Summary Chapter 3. Modifying an Existing System Identifying What to Modify Beginning Your Optimization Analyzing Target Areas Performing the Optimizations Summary Part II: Getting Our Hands Dirty Chapter 4. Tools and Languages Tools You Cannot Do Without Optimizing with Help from the Compiler The Language for the Job Summary Chapter 5. Measuring Time and Complexity The Marriage of Theory and Practice System Influences Summary Chapter 6. The Standard C/C++ Variables Variable Base Types Grouping Base Types Summary Chapter 7. Basic Programming Statements Selectors Loops Summary Chapter 8. Functions Invoking Functions Passing Data to Functions Early Returns Functions as Class Methods Summary Chapter 9. Efficient Memory Management Memory Fragmentation Memory Management Resizable Data Structures Summary Chapter 10. Blocks of Data Comparing Blocks of Data The Theory of Sorting Data Sorting Techniques Summary Chapter 11. Storage Structures Arrays Linked Lists Hash Tables Binary Trees Red/Black Trees Summary Chapter 12. Optimizing IO Efficient Screen Output Efficient Binary File IO Efficient Text File IO Summary Chapter 13. Optimizing Your Code Further Arithmetic Operations Operating System–Based Optimizations Summary Part III: Tips and Pitfalls Chapter 14. Tips Tricks Preparing for the Future Chapter 15. Pitfalls Algorithmic Pitfalls Typos that Compile Other Pitfalls
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值