The world at your fingertips — 天涯明月刀幕後22(優化)
來自專欄遊戲開發隨筆
多進程載入
32位系統中,內存的使用上限只有2G,打上系統補丁,可以用到3G。對於一個MMO,這點內存不太夠。早期開發並不重視,內存該用就用,飛奔向前的項目,很快迎面撞上了內存牆。
第一波遇上問題的是編輯器。在改用大地形體系後,內存馬上吃緊。有幾張內容比較充實的地圖,已經沒有足夠的內存可以跑。於是大家開始注意內存使用,用上了各種streaming手段,確保美術能正常工作。
再往後,在遊戲中的內存也不夠了。玩家的電腦普遍都有4-8G的內存,但是我們的遊戲只能用2G。於是streaming系統進一步被加強改善,確保隨時只使用最精簡的數據集合。
為了改善內存情況,一方面要節約,我們需要減少無謂的浪費,另一方面也需要開源,尋找一些方法使用更多的內存。
某次看技術文章的時候,突發奇想,windows系統可以跨進程做內存共享,那如果我把大量內存放在其他進程,然後再映射回我的遊戲,每次在一個滑動窗口中訪問,不就可以使用更多的內存了。
想歸想,實際要用起來還是不太方便,對邏輯代碼影響比較大,很多時候內存不能直接訪問,要封裝一層,帶來了不小的改動成本和運營時刻開銷了。
想法暫時按下,但心卻狂野奔放,尋找著宣洩的出路。
終於有一次做版本的時候,內存又爆了,我們分析內存佔用,留意到為了減少卡頓,程序員分配了一個大約100m的預先緩存buffer,在載入線程中不停做預讀取。暫時先禁用了他的預讀取,確保程序能正常使用,同時我想了一下,動態streaming和預讀取,正好很符合我那個預讀取的場景。於是我規划了一下,找何老師做了預載入進程,把所有的載入邏輯放到了新的進程中,和主線程做一些進程間的通信,接受主線程的載入建議,做按需載入,也會自主做一些提前預載入,放進分配的內存,然後通過進程間的內存共享機制,把載入的數據,共享給主進程使用。主遊戲進程,永遠只要維護一個很小的內存窗口,大量的內存數據,都在另一個進程中。
雖然工作量不小,但這樣做有很多好處。
首先,所有的訪問io的操作,都是streaming系統接管,這意味著所有的改動,並不會影響所有上層的邏輯代碼,因為它們本來就是通過streaming系統來非同步訪問的,所有改動對上層造成的影響,到streaming系統為止,不會往上傳遞。這樣整個系統的複雜度得到了很好的降低。
其次,跨進程訪問造成的複雜度以及對性能的影響,和streaming系統面對的低速IO相比,都不算個事,可以認為不會比原來系統更慢。
再次,這個系統是scalable的,根據玩家內存不同,可以更激進的分配緩存內存,對於高端電腦,獨立載入進程可以用更多的內存,更多緩存常用數據,由於這些緩存數據是跨進程的,帶來了新的好處,如果玩家喜歡雙開遊戲,也會從中獲益,可以共享這部分內存。雙開遊戲如果要去同一個地圖的同一個地方,則緩存的數據會被重用,第二個遊戲窗口的載入速度就非常快。
最後,由於跨了進程,所以我們可以用到大於2G的內存,降低了主遊戲進程的內存壓力。
附帶的一個好處,是這個模塊是完全可以在不同遊戲中復用的,因為所有的輸入輸出都是標準化的,它本身也不知道上層的邏輯,只負責離線IO,所以重用性比較高。
為了充分加快載入速度,我們也做了很多別的優化,比如chrome瀏覽器開發團隊介紹過的操作系統預讀法,又比如根據玩家位置,如果靠近關卡傳送點,也會提前載入一些其他關卡的數據,反正一切讀寫硬碟的io操作都是非同步的,根據我們的各種預判,可以儘可能多的做一些預先載入工作。而獨立這個載入系統在外部,也可以很好的降低主遊戲的開發複雜度。
優化
由於遊戲scope越來越大,後期我們對產品效率開始做了深入的優化。
以往做主機,傳統項目的優化,一般是2-3個資深程序員,做上2-3個月就差不多了,天刀這個項目,優化基本持續了整個項目的始終。從很早期開始,我們就一直有人在做優化的工作,一直持續到項目上線。
PC的優化是一個不太好做的事情,機器配置千變萬化,PC優化也是一個幸福的事情,可用的工具集非常強大。
優化中我們的主要原則有幾個。
先是能更好的收集性能問題。我們建立了持續測試的框架。常見的性能問題點,都覆蓋了非常多的性能收集點,經常跑一下,隨時可以留心到性能異常。也有dashboard,可以定期根據地圖,遍歷各個位置,跑性能收集,畫熱度圖。同時也在項目中普及了查找性能問題的流程,策劃美術在運行遊戲的時候,碰到性能問題,可以隨時截取相關數據,然後放聲尖叫,召喚程序員過來查找問題。
再是工具層面做好充分的研究。每一種工具,都有擅長解決的問題,和不擅長解決的問題,要對症下藥。有些工具可以快速給你性能全貌,有些工具擅長解決卡頓問題,有些工具實時監控引擎性能,有些工具只能離線分析。在不同的場合,使用不同的工具處理,會有不同的驚喜。
三是定期有大型長期的優化目標。針對專項領域,我們一般都會安排有人花整段時間去研究,且這個優化的人,每個階段是輪換的。這有很多好處,從個人成長角度看,每個人去玩一下優化,有助於變成一個更好的程序員,知道了性能開銷,就不會亂寫代碼。當然我們去優化的人一般比較senior,這個不是最大的考慮因素。最大的因素是考慮到每一個開發人員都有盲區。我一直profile一個東西,可能久而久之,就有盲點了,對很多問題視而不見,思路會受限。換一個人,一眼就有可能發現裡面的問題。
四是在性能優化方面,重點關注卡頓問題,而不是平均幀數問題。很多時候遊戲平均幀數其實不低,一直在50幀以上,但只要某一幀卡頓一下,有100ms以上的延遲,就很容易能感覺到幀數問題。我們在中後期,專註看卡頓問題,嘗試解決所有100ms以上的卡頓問題,發現一個解決一個。這裡的問題並不容易解決,大多數同類卡頓是因為不小心用了同步的硬碟io,但也有很多是一次創建太多材質紋理,一次創建過多對象,或者是一次初始化過多物件。修改這些問題,往往要深入引擎內部,進行細緻調整,或者修改一些系統的實現方式,才能緩解卡頓。為了做好這些優化,我們把所有載入都非同步化,對所有可能造成性能瓶頸的初始化、創建部分也做了控制,這些系統有嚴格的時間預算控制,超過了,本幀就跳過,留給下一幀繼續處理。
經過數個版本的優化,效果應該說是相當理想的。由於渲染的東西夠多,我們的平均幀數並不能如當時同類遊戲一樣高,但玩家普遍反映很流暢。在遊戲運行過程中幀數變化比較平均,所以整體感受是比較流暢。
當然也不是所有的性能問題都會影響感受,比如好多遊戲放大招的時候,由於太多全屏特性,會有劇烈的卡頓,然而玩家不怒反喜,有種莫名的快感,那是積攢多時的鬱悶,那是心靈釋放的解脫。我們把這種快感稱之為技能越強卡頓越大快感越爽綜合症,越大的招數,自然要卡頓,讓玩家能感受到其中的快感。對於這類問題,我們降低優先順序,但最後還是全處理了一下。一個穩定的幀數,對整體遊戲品質,是有巨大影響的。
顧煜:天涯明月刀幕後(總目錄)推薦閱讀:
※000_Introduction 介紹
※線程小遊戲(一)
※星游視野:如果你接手了一款糟糕的遊戲……
※GMS2官方教程系列4/8——瓷片&鏡頭