面向数据编程
面向對象編程層層抽象造成臃腫,導致運行效率降低,而這是性能要求高的游戲編程領域不想看到的。
面向過程:建立解決問題所需的各個步驟(函數)。
面向對象:建立解決問題所需的各個模型(類)。
面向數據:考慮數據的存取及布局(數據)。
值得一說的是,面向過程和面向對象都是解決問題的一種方法,而面向數據只是一種優化的設計思想,而非解決問題的方法。
冷數據/熱數據分割
我們希望CPU緩存存儲的是經常使用的數據,而不是那些少用的數據。這就引入了冷數據/熱數據分割的概念了。
熱數據:經常要操作使用的數據,我們一般可以直接作為可直接訪問的成員變量。
冷數據:比較少用的數據,我們一般以引用/指針來間接訪問(即存儲的是指針或者引用)。
一個例子:對于人類來說,生命值位置速度都是經常需要操作的變量,是熱數據。
而掉落物對象只有人類死亡的時候才需要用到,所以是冷數據;
頻繁調用的函數盡可能不要做成虛函數
C++的虛函數機制,簡單來說是兩次地址跳轉的函數調用,這對CPU緩存十分不友好,往往命中失敗。實際上虛函數可以優雅解決很多面向對象的問題,然而在游戲程序如果有很多虛函數都要頻繁調用(例如每幀調用),很容易引發性能問題。
解決方法是,把這些頻繁調用的虛函數盡可能去除virtual特性(即做成普通成員函數),并避免調用基類對象的成員函數,代價是這樣一改得改很多與之牽連代碼。所以最好一開始設計程序時,需要先想好哪些最好不要寫成virtual函數。
重新認識C++ STL容器
STL容器,特別是set,map,有著很多O(logN)的操作速度,但并不意味著是最佳選擇,因為這種復雜度表示往往隱藏了常數很大的事實。
例如說,集合的主流實現是基于紅黑樹,基于節點存儲的,而每次插入/刪除節點都意味著調用一次系統分配內存/釋放內存函數。這相比vector等矢量容器所有操作僅一次系統分配內存(理想情況來說),實際上就慢了不少。
此外,矢量容器對CPU緩存更加友好,遍歷該種容器容易命中緩存,而節點式容器則相對容易命中失敗。
綜合上述,如果要選擇一個最適合的容器,那么不要過度信賴時間復雜度,除非你十分徹底的了解STL容器,或對各容器進行多次效率測試。
總結
對面向對象和面向數據的看法:應該兼有。
因為游戲程序是一個既需要高性能又復雜的工程。使用面向對象的游戲程序新手,常常就有一個問題:過度設計/過度抽象,什么都想用設計模式封裝一下抽象一下。這就很容易導致一些過度設計/過度抽象導致游戲性能太差。
面向數據思想,盡量減少虛函數的使用,多利用數據組合成對象,而不是重寫各種基類虛函數。對于一些數據結構的考量,也盡量偏多使用連續存儲的結構(例如數組)。
總結
- 上一篇: 通信标准3之PUSCH频率域资源分配
- 下一篇: android11.0 12.0Laun