最近看完了《C++性能白皮書》,這本書列出了一些性能優化的思路,不過只是一些指引,沒有講具體細節,我整理出了其中的關鍵點分享給大家:
硬件篇
作為一個程序員,想要性能優化,最好要了解些硬件,特別是CPU架構的一些知識點:
流水線
分支預測
寄存器重命名
數據預取
指令重排和亂序執行
同時多線程(超線程)
數據并行 SIMD 單指令多數據
還要了解CPU的特點:
一個處理器上,多條指令可能同時執行
一個處理器上,代碼的執行結果會和程序員可觀察到的順序一致,但其他處理器觀察到的執行結果可能不是一個順序
順序、無跳轉的代碼性能最高
相鄰且對齊的數據訪問性能最高
內存方向的優化:
金字塔圖需要了解
還需要了解CPU多級緩存和關鍵跨度的概念,這塊可以看這篇文章:https://mp.weixin.qq.com/s/iKWQZxn6XYKU9KnlBRynfg
要了解基本工具:
編譯器:MSVC GCC clang
不同級別的優化:O1 O2 O3 以及他們的主要區別
需要知道性能分析指導下的優化:PGO profile-guided optimization
也就是利用程序運行的profiling數據,指導編譯器進一步優化。多測試,找到程序熱點,根據數據針對性優化。
還有鏈接期優化:link-time optimization LTO
LTO可以:
跨翻譯單元的函數內聯
跨翻譯單元的程序整體優化
死代碼消除
做性能優化,需要了解性能測試的阿姆達爾定律,80-20原則,20%的代碼決定了80%的結果,如果對20%以外的代碼進行優化,性價比太低,性能測試的意義就在于此:
找出代碼中性能開銷最大的部分
測量代碼優化之后的實際收益
需要熟練使用性能采樣工具:
Windows中Visual Studio有自帶的性能分析工具
Linux有Perf或者gperftools
C++篇
關于C++語言層面的優化,可以在下面這些方向做優化:
優先棧內存,次之堆內存
巧妙使用RAII管理資源
移動語義雖然不好理解,但也可以巧妙使用移動語義減少對象的非必要拷貝
模板和泛型技巧華而不實,給開發標準庫的人使用還好,而且調試難度也較高,我們普通業務開發者只需要做到能看懂即可(個人見解)
異常是可以考慮使用的,可以看看ISO C++網站和C++ 核心指南62,異常會導致程序的二進制體積有膨脹(5%-15%),異常不能代替所有的錯誤碼,因為異常catch會使得程序性能下降。作者認為:使用異常對于大部分C++項目仍然適用,不使用異常的麻煩大于好處,除非真因為二進制文件和實時性方面的原因需要禁用異常。
字符串默認類型時 const char[],傳參時會退化成const char*,創建全局字符串最好使用const char[]
標準庫容器的方法至少提供了基本異常安全保證:要了解強異常安全保證和無異常保證。
vector的移動構造函數標記為noexcept才會使用移動構造,移動構造函數需要標記為noexcept,如果沒有標記,代碼性能可能會有較大的負面影響。
shared_ptr構造優先使用make_shared
10.了解function,function用作回調很方便,支持類型擦除,它還有個好處,可以用來存儲帶狀態的函數對象,不像C語言那樣需要個void*存儲狀態。但需要了解它的開銷,貌似48個字節是個坎。
13.并發
需要了解內存序的概念 一些優質的多生產者多消費者并發隊列
moodycamed::ConcurrentQueue atomic_queue Folly中MPMCQueue
標準庫也有些并行策略:
execution::seq 序列執行,不可并行 par:可并行化
par_unseq:可并行化 向量化
unseq:可向量化
通用方法篇
通用優化方法
優化原則:不要執行不必要的代碼
循環優化,盡量減少臨時對象的創建
結構體設計時最好做到對齊
盡量順序訪問數據,矩陣乘法可以很好的印證CPU Cache的作用,再考慮添加-O3 -march=native開啟SIMD自動向量化
緩存爭用問題
多看看別人的代碼,別人的優化,多用優秀的開源代碼
這里有 一個優質的C++學習圈 等你加入,來一起鉆研C++吧。