針對一個渲染引擎的效能,最主要的當然是實時渲染的影格率。另一方面,對於輕型的引擎來說,使用者不會對場景載入
保有一個較長的載入時間的心理預期,最好是,點選按鍵,瞬間整個場景出現,畢竟輕量應用場景不是重型遊戲。針對
這種需求,我們需要對資源載入做一個全面的效能排查與優化。
根據《Unix程式設計藝術》中的描述,效能優化最好是不要優化,如果要優化那麼花費一點時間把 bottle neck 找到是很有
必要的。所以在我的優化工作中,我首先對整個系統做了較為完整的 profile. 我大致將整個資源載入部分邏輯分成了
自頂向下的三層:
對我們的整個引擎的載入部分,分層級自上而下統計,對每個 meshrender 統計得到的情況如下表,其中分別有幾個模組:
Mesh Material Skin 各佔一部分,同時圖片的載入已經使用了非同步執行緒載入方式,故不統計在總時間內(載入圖的子
執行緒在主載入執行緒完成任務之前就已經完成結束)。從下表資料看,Mesh 與 Material 均佔較大部分的比例,所以在下面
detailed 層,專門針對這兩個部分繼續剖析。
- | Img Load(Async) | Mesh | Material | Skin | Others | Total |
---|---|---|---|---|---|---|
Current | 31.07 | 40.85 | 101.70 | 8.27 | 3.04 | 153.86 |
Detailed 分析分別對幾個不同的模組進行了分析。其中 Mesh 的載入雖然耗時較長,但是實際時間絕大部分用在將 mesh
資料從檔案中讀取到記憶體,並沒有發現其他可能浪費時間的耗時操作,邏輯上也比較簡單,故結論是無優化空間。
另外 Material 部分,其邏輯就比單純載入一塊 mesh 的buffer 要複雜許多了。其中包括了特定物件 MaterialAsset 的
建立與初始化,shader 的載入以及解析,啟動非同步讀圖執行緒等等。具體的耗時分佈如下表所示。
- | Get AbsPath | Material Asset | Shader | Async load imgs | Others | Total |
---|---|---|---|---|---|---|
Current | 1.38 | 1.77 | 8.20 | 1.71 | 1.10 | 14.15 |
其中 shader 部分是耗時大頭,此處 shader 並不僅僅包括 shader 檔案的載入,還有其中一些 uniform
變數的解析,
探究其邏輯發現兩點
針對這兩者情況我都做了相應的優化
std::vector<>
在傳遞時幾乎沒有損耗優化以後的資料如下表
- | Get AbsPath | Material Asset | Shader | Async load imgs | Others | Total |
---|---|---|---|---|---|---|
Current | 1.38 | 1.77 | 8.20 | 1.71 | 1.10 | 14.15 |
Optimize | 1.52 | 1.85 | 7.44 | 1.28 | 0.52 | 12.61 |
在 Skin 的載入部分同樣找到了部分多餘的值 copy 操作,優化為參照後資料略有提升。
最後我們來看一下總體的效能提升情況
- | Img Load(Async) | Mesh | Material | Skin | Others | Total |
---|---|---|---|---|---|---|
Current | 31.07 | 40.85 | 101.70 | 8.27 | 3.04 | 153.86 |
Optimize | 33.62 | 36.40 | 80.81 | 6.88 | 3.28 | 127.37 |
Performance of resource loading
Mesh Material Skin Others
before opt xxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|xxx|x|
after opt xxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxx|xx|x|