【厚積薄發】關於LZMA和LZ4壓縮的疑惑解析

【厚積薄發】關於LZMA和LZ4壓縮的疑惑解析

來自專欄 UWA:簡單優化、優化簡單

這是第112篇UWA技術知識分享的推送。今天我們繼續為大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。

UWA 問答社區:answer.uwa4d.com

UWA QQ群:465082844(僅限技術交流)

AssetBundle

Q:昨天看到問答社區上UWA_Xin對LZMA和LZ4壓縮的解答,在此有些疑問。

問題1:

Unity資源解決方案之AssetBundle - AaronBlogs - 博客園?

www.cnblogs.com圖標

我在網上看到這篇文章提到,AssetBundle在載入的時候需要擴展出來一塊內存來解壓,我覺得解壓這個說法是有問題的,因為如果都被解壓出來了,就不需要LoadAsset了。資源都已經在內存中了,而我們測試的時候,用LZ4要比LZMA內存小了快200MB,所以我覺得LZMA是在載入AssetBundle的時候會把資源都解壓出來的,並不是只是多了一個LZ4的AssetBundle大小。

我看了UWA關於《移動遊戲載入性能和內存管理全解》的視頻講解,上面說用LZMA壓縮的時候LoadFromCache在第一次讀取時會很耗時,是由於Cache會把AssetBundle包重新壓縮成LZ4使得第二次讀取的時候速度加快,所以上面截圖說的LZMA會把AssetBundle再壓縮成LZ4其實只是針對的LoadFromCache這個介面而言的,而不是針對的LoadFromFile,猜想LoadFromFile是直接從硬碟讀取的,不存在Cache的操作,所以上圖是不是說得有誤?

問題2:LZ4壓縮AssetBundle包是按照Chunk來讀取的,那麼在解壓AssetBundle包的時候一般是在讀取AssetBundle的頭文件信息,那麼解壓AssetBundle包的時候LZ4的Chunk優勢是沒有優勢的嗎?載入AssetBundle的時候LZMA和LZ4的速度應該一樣的嗎?(如果LZMA是完全解壓整個包體就另當別論了)。

UWA:問題1解答:我覺得解壓這個說法是有問題的,因為如果都被解壓出來了,就不需要Loadasset了,資源都已經在內存中了。

解壓和載入是兩回事的。題主給的文章里說的解壓是針對WWW介面的,WWW載入LZMA,是需要解壓進內存的,但這個只能算是二進位流,相當於是未壓縮的AssetBundle,後續的LoadAsset依然是要做的…但第二次調用的LoadFromCache就不用了,因為磁碟的Cache里已經是「未壓縮的AssetBundle」了。

上面截圖說的LZMA會把AssetBundle再壓縮成LZ4,這不僅僅是針對LoadFromCache的,LoadFromFile也是一樣,只是LoadFromFile是不Cache到磁碟的,完全在內存中進行,所以這個介面載入LZMA的AssetBundle一樣會變很慢,同時造成內存的明顯上漲。

問題2解答:根據問題1的解釋,LZ4相比LZMA在載入AssetBundle的時候還是有很大優勢的。但最後還是留下了一個疑問,而我們測試的時候用LZ4,要比LZMA內存小了快200MB,所以我覺得LZMA是在載入AB的時候會把資源都解壓出來的,並不是只是多了一個LZ4的AssetBundle大小。經過這邊的一些測試,這個內存的差異確實更加接近未壓縮的AssetBundle的大小,而不是LZ4的大小。

所以題主可不可以再多做一步,就是把用到的AssetBundle打成未壓縮的,看看是不是確實接近200MB呢?

該回答由UWA提供,歡迎大家轉至社區進行進一步交流:

關於LZMA和LZ4壓縮的一些疑惑的地方 - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標

粒子系統

Q:粒子系統是否能夠支持GPU Instancing?做了些例子都沒能看到GPU Instancing生效。

UWA:Unity 2018已經支持Particle System的GPU Instancing了,不過必須是Mesh模式的,具體可以看這個文檔:

Particle System GPU Instancing?

docs.unity3d.com圖標

該回答由UWA提供,歡迎大家轉至社區進行進一步交流:

粒子系統對GPU Instancing的支持?

answer.uwa4d.com圖標

載入

Q:如果我代碼中聲明了個Texture然後載入了圖片,是不是無論我的這個Component銷毀或者這個GameObejct銷毀,都不會釋放這個Texture的內存?必須在OnDestroy 里銷毀才可以呢?

A1:因為某張Texture的內存只會有一份,但是可能會被多個對象引用,所以不可能跟隨Component或GameObject的銷毀而銷毀。

估計是考慮到資源管理(某張Texture當前幀不用了,可能過兩幀又要用了,而這部分IO消耗不小,所以需要開發者自行管理),所以這部分並沒有走GC。使用Resources.UnloadAsset卸載Texture。

感謝凱奧斯@UWA問答社區提供了回答

A2:Component銷毀 或者 Gameobject銷毀都不會卸掉new出來的Texture的內存,需要調用Object.Destroy()方法,把new出來的Texture對象作為參數傳進去,然後查看Profiler就可以驗證。

感謝上午八點@UWA問答社區提供了回答

歡迎大家轉至社區進行進一步交流:

Texture 垃圾回收問題 - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標

編輯器

Q:有辦法臨時屏蔽掉腳本的一些編譯Warning嗎?比如 The variable xxx is declared but never used之類的。

A1:File->Build Settings->Player Settings->Logging

感謝凱奧斯@UWA問答社區提供了回答

A2:強烈建議題主修掉這些Warning,而不是屏蔽掉它們。我覺得,程序保證代碼沒有Bug是底線,沒有Warning是合格線……尤其是你舉例的這種,雖然編譯器會幫你做優化,但是保不齊什麼時候寫其他邏輯的時候會坑了你。

感謝賈偉昊@UWA問答社區提供了回答

歡迎大家轉至社區進行進一步交流:

如何屏蔽編譯warning - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標

動畫

Q:遊戲在運行一段時間後,出現了一個CPU高佔用函數:Director.ProcessPlaySateChanges ,它產生了3616ms的耗時,請問這是怎麼產生的,確認C#代碼中無此方法調用,有人遇到過這個問題嗎?(版本Unity 5.6.5p3)

A:經排查已找到原因,是UI中的一個播放動畫前調用了函數 Animator.Rebind()導致的。

感謝張劍@UWA問答社區提供了問題和回答,歡迎大家轉至社區進行進一步交流:

Director.ProcessPlaySateChanges是什麼調用? - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標


今天的分享就到這裡。當然,生有涯而知無涯。在漫漫的開發周期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站(answer.uwa4d.com)上準備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之「石」,也能攻你之「玉」。

官網:www.uwa4d.com

官方技術博客:blog.uwa4d.com

官方問答社區:answer.uwa4d.com

官方技術QQ群:465082844(僅限技術交流)

推薦閱讀:

架空世界 之 公式創世
導出範疇如何決定代數簇的結構?
偏科只能偏數學(五)
清華MOOC有限元課程學習筆記(七)

TAG:數學 | 性能優化 |