系列文章目錄
C++高性能優(yōu)化編程系列
深入理解設(shè)計原則系列
深入理解設(shè)計模式系列
高級C++并發(fā)線程編程
1、為什么要進行性能優(yōu)化
不好的編程習(xí)慣,不重視程序性能測量分析讓代碼跑的更快,會導(dǎo)致浪費大量的CPU周期、程序響應(yīng)時間慢以及卡頓,用戶滿意度下降,進而浪費大量的時間返工去重構(gòu)本應(yīng)該一開始就更加高效的代碼。性能優(yōu)化與編碼對開發(fā)過程而言有著同等的重要性。對于用戶而言,性能糟糕的讓人無法接受,這個問題的嚴重程度不亞于出現(xiàn)bug和未實現(xiàn)的特性。
性能優(yōu)化的目的:是通過改善正確的程序行為使?jié)M足客戶對處理速度、吞吐量、內(nèi)存占用以及能耗等各種指標(biāo)的需求。
2、性能測試的指標(biāo)是什么
- 啟動時間
通過測量程序進入main()函數(shù)到進入主循環(huán)的時間來得到啟動時間。 - 退出時間
通過測量接收退出命令到程序退出main()的時間來得到退出時間。(退出時間也包含停止所有的線程和所依賴的進程所需的時間) - 響應(yīng)時間
執(zhí)行一個命令的平均時間或最長時間。 - 吞吐量
在一定的測試負載下,系統(tǒng)在每個時間單位內(nèi)所執(zhí)行的操作的平均數(shù)。更適合批量處理程序。
3、測量性能及改善變更記錄文檔
優(yōu)秀的開發(fā)人員都會系統(tǒng)的完善他們的開發(fā)任務(wù):
- 做出的預(yù)測都是可測試的,并且記錄下預(yù)測;
- 保留代碼的變更記錄;
- 可以使用最優(yōu)秀的工具進行測量;
- 保留結(jié)果的詳細筆記。
4、性能測量分析工具的使用
4.1、使用Linux Perf性能分析器進行性能測量分析
介紹一下第一個性能分析器工具Linux Perf性能分析器。這是Linux上流行的性能分析器之一,因為它隨大多數(shù)發(fā)行版一起安裝。此性能分析器使用硬件性能計數(shù)器和基于時間間隔的采樣結(jié)合起來,記錄正在運行程序的性能分析。它將記錄每個樣本程序計數(shù)器的位置(要執(zhí)行的指令的地址)和用戶正在監(jiān)控的性能計數(shù)器的值。運行該性能分析器后,即可對數(shù)據(jù)進行分析;樣本最多的函數(shù)和代碼占據(jù)大部分執(zhí)行時間。
值得注意的是,性能分析器在運行時收集指令地址,要將其轉(zhuǎn)換為原始源代碼中的行號,必須使用調(diào)試信息編譯程序。使用兩種編譯模式組合:optimized(優(yōu)化)和debug non-optimized(調(diào)試非優(yōu)化) - 調(diào)試和優(yōu)化都被啟用。
使用這種選項組合的原因是我們需要分析將在生產(chǎn)環(huán)境中運行的相同代碼,否則數(shù)據(jù)大多沒有意義。
計數(shù)器
cycles(周期):cycles時間是CPU頻率的倒數(shù)。
instructions(指令):可測量已執(zhí)行的處理器指令數(shù)。
branches(分支):是條件指令,每個if語句和每個帶條件的for循環(huán)都將至少生成這些指令之一。
branch-misses(分支未命中):
cache-references(緩存引用):統(tǒng)計的是CPU從內(nèi)存中獲取某些東西所需的次數(shù)。大多數(shù)情況下,這里說的“某些東西”是一段數(shù)據(jù),例如字符串中的一個字符。根據(jù)處理器和內(nèi)存的狀態(tài),這種獲取可能非常快,也可能非常慢。對于慢的,計入cache- misses。
cache-misses(緩存未命中):代碼中低效的內(nèi)存訪問,訪問速度非常慢。
4.2、使用Google GperfTools性能分析器進行性能測量分析
Gperftools是google開發(fā)的一款非常實用的工具集,主要包括:性能優(yōu)異的malloc free內(nèi)存分配器tcmalloc;基于tcmalloc的堆內(nèi)存檢測和內(nèi)存泄漏分析工具heap-profiler,heap-checker;基于tcmalloc實現(xiàn)的程序CPU性能監(jiān)測工具cpu-profiler.
Goole CPU性能分析器可以使用硬件性能計數(shù)器,還需要代碼的鏈接時檢測(但不需要編譯時檢測)。要準(zhǔn)備用于性能分析的代碼,必須將其與性能分析器的profiler庫鏈接。
與Linux Perf不同的是,Google CPU性能分析器不需要任何特殊的工具來調(diào)用程序,必要的代碼已連接到可執(zhí)行文件中。
已檢測的可執(zhí)行文件不會自動開始性能分析。因此,我們必須通過將環(huán)境變量CPU PROFILE設(shè)置為想要存儲結(jié)果的文件的文件名來激活性能分析。
5、性能測量微基準(zhǔn)測試分析
5.1、使用計時時間測量函數(shù)執(zhí)行時長微基準(zhǔn)測試分析
用一個Stopwatch類來測量程序中部分代碼的執(zhí)行時間并分析代碼,以下是我編寫的一個計時類的代碼:
/*
* @Author: Allen
* @Date: 2023/5/26
* @Description: 函數(shù)測量計時
*/
#ifndef STUDYTEST_STOPWATCH_H
#define STUDYTEST_STOPWATCH_H
#include <iostream>
#include <chrono>
using namespace std::chrono;
class Stopwatch {
public:
/*
* 初始化構(gòu)造函數(shù)
* _activity:傳遞功能名稱用于log打印
* */
explicit Stopwatch(char const* _activity = "Stopwatch"){
activity_ = _activity;
start_ = steady_clock::time_point::min();
}
~Stopwatch()= default;
/*
* 開始計時
* */
void Start(){
std::cout << "[ " << activity_ << " Start ]" << std::endl;
start_ = steady_clock::now();
}
/*
* 判斷是否已開始計時
* */
bool IsStarted() const{
return start_.time_since_epoch() != steady_clock::duration(0);
}
/*
* 清除計時
* */
void Clear(){
start_ = steady_clock::time_point::min();
}
/*
* 獲取間隔時間
* */
unsigned long GetMS(){
if (IsStarted()){
steady_clock::duration diff;
diff = steady_clock::now() - start_;
return (unsigned)(duration_cast<milliseconds>(diff).count());
}
return 0;
}
/*
* 停止計時
* */
void Stop(){
unsigned long interval = GetMS();
std::cout << "[ " << activity_ << " Stop ] Use Time : " << interval << "ms" << std::endl;
Clear();
}
private:
steady_clock::time_point start_;
char const* activity_;
};
#endif //STUDYTEST_STOPWATCH_H
引入Stopwatch類使用:
{
Stopwatch sw("MyString");
sw.Start();
{
// 運行的熱點函數(shù)代碼
// ...
}
sw.Stop();
}
運行結(jié)果打?。?mark hidden color="red">文章來源:http://www.zghlxwxcb.cn/news/detail-463540.html
[ MyString Start ]
[ MyString Stop ] Use Time : 20ms
5.2、使用Google Benchmark庫微基準(zhǔn)測試分析
google benchmark主要是對c++中的函數(shù)進行基準(zhǔn)功能測試。文章來源地址http://www.zghlxwxcb.cn/news/detail-463540.html
到了這里,關(guān)于C++高性能優(yōu)化編程之如何測量性能(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!