Coroutine的文章太難寫了,只好先寫篇簡單的
這是一篇工程性的文章,給對這方面有興趣的人
Motivation
由於看了某AI部門寫的C++服务编译耗时优化原理及实践這篇文章,想要分享一下思路 ,不過編譯二十分鐘就在哀哀叫 (當初我前公司動輒一兩個小時
Clarification
- 這問題跟C++無關,這是C語言的問題
- C++的編譯模型跟C語言一樣(Before C++20)
- 不過由於C++有template和header only libraries而將這問題放大了很多倍
- 不信的話可以試試看編譯Linux kernel
Root Cause
哪有什麼Root Cause,這不是個Bug
只是跟不上時代
C語言誕生在1969-1973,至今超過五十年了
當初計算機能力比不上現代,因此產生了
Header / Implementation Separation的做法
C++繼承了這個Compiling Model
Modern Language怎麼做
將宣告和實做擺在一起
- Application Language: Java/C#/Javascript/Golang
- System Language: Zig/Rust
About Future
分兩方面來說
C
C語言已經是個Inactive的語言了
- 自從C11之後,不加入重大新功能,只做相容性改善
- 別期待它會加入Module功能
C++
相較於C,C++從11之後努力追趕Modern Language的路線
- 直到C++20之後,才推出正式的Module Spec
- 不過何時可以用上未可知
- Cloud端也許明年就能使用,embedded等vendor改朝換代不知道要多久
- 就算全面普及之後,ecosystem也要一段時間才能趕上
- 以Javascript為例,從commonJS切到Module也走了五六年
What can we do now
未來會怎麼發展不知道,不過現在有幾個選項
什麼都不要做
這不是Bug,不管它也無妨,如果真在意編譯速度的話,當初我前公司買Incredibuild做分散式編譯
根據最前面那篇文章的數據,使用分散式編譯效果比其他方法都有用
Precompiled Headers
將常用的header通通include在一起,然後編譯這個大的header file
有興趣可以參考Using pre-compiled headers in GCC/Clang using CMake and usage in Catch2
Reduce Header dependency
這可以分成幾方面來討論
Find unused header
舉個例子
1 |
|
stdio.h
在這邊就是完全沒必要的,如果是goalng,import fmt
然後沒用到根本編譯不過,不過golang這作法是個雙面刃,我不喜歡
如果要工具的話可以考慮[include-what-you-use](
Choose suitable third party libraries
不可能所有東西都自己寫,當你需要某個功能的時候,先找找是否有適合的選項,問題是如果選擇太多了該怎麼辦,總不能
文中討論到Boost,Boost最大的問題是它依賴性太重了
當你需要一台腳踏車的廠警,選擇一台坦克車絕對不是個好主意
Opaque Pointer
俗稱編譯防火牆的技術,是當的斷開header dependency
以C語言來說,header大概長這樣
1 | struct obj; |
implementation是這樣
1 |
|
C++版的叫pImpl,如果有看過我的程式碼應該不陌生,掠過
1 |
|
Conclusion
雖然這不是個Bug,不過有人題就表示這是個需求,未來會怎麼走沒人知道,只能現有的材料下能做些什麼改進