ServerLight內存及網頁素材保護

 

一)內存釋放

首先,希望大家強烈認識到Silverlight程序是託管的,除特別明顯或強烈的需要外(例如OpenFileDialog、SaveFileDialog等繼承自IDisposable接口的類),望大家不要輕易介入GC.Collect(),這是微軟設計.NET的初衷,我們僅能且必須做的就是:信任。

其次,需要所有精通.NET開發語言的朋友再次確認自己是否對數據類型有深刻理解。以C#爲例,在編寫代碼時尤其要分清值類型引用類型,包括它們的定義、組成及原理。因爲值類型對象在賦值後其內存可以很快釋放掉。以Struct(結構)和Class(類)爲例,如果不需要實現繼承,使用值類型可接口的Struct將得到比Class更高的性能。另外,在書寫類內部時,儘量不要使用私有類對象;同時要注意如果一個類一直被其他類所引用着,內存同樣無法被釋放。在與其他Silverlight開發者交流中經常會聽到類似這樣的抱怨:Storyboard太耗內存了,Storyboard性能太低下了,Storyboard太……無語了。俗話說:成也蕭何,敗也蕭何,這些症狀均是Storyboard類被濫用的結果。這裏的“濫”包含兩層意思:1、不會用;2、用過度。一個好工具要物盡其用,則必須精通它的原理與細節。Storyboard是否無意中被放進了循環裏?是否出現了委託泄漏?Storyboard在Completed後其他對象是否仍在引用着它?Storyboard是否忘記停止啦?等等。包括DispatcherTimer也一樣,Silverlight在爲我們製作各種流暢動畫效果提供便利工具的同時,我們是否也應該讓代碼做到更嚴謹些呢?

小結:Silverlight內存釋放最終還得看自己,簡單說就是:只要夠精通,夠專業,沒有釋放不掉的內存。作者也在朝這個方向努力着。

二)性能提升

1)在第三節中我曾有提到利用BackgroundWorker在後臺線程中執行相對耗時的操作進而減少Silverlight界面線程的負擔。其實,我們同樣還可以通過異步的方式提高畫面的流暢度,比如:

this.Dispatcher.BeginInvoke(() => {

       //TODO…

});

Dispatcher是WPF/Silverlight機制的核心,深入理解它有助你編寫更高性能的代碼。

2)在動畫及遊戲開發中儘量減少不必要的呈現、重繪(例如在Canvas.SetLeft前先判斷Canvas.GetLeft是否與Value值相同);隱藏掉不在屏幕中的圖象載體(obj.Visibility = Visibility.Collapsed),對圖象進行切割,減少窗體中的圖片數量,對相同或類似圖片儘量做到複用,監控好委託的訂閱與取消訂閱(訂閱N次將執行N次操作,如果發生在循環裏極易造成內存泄露甚至程序崩潰,請初學者認識到這點)等等,雖然均是些細節,但效果往往卻非常明顯。

3)調整好最大FPS,Silverlight中的MaxFrameRate可以通過Application.Current.Host.Settings.MaxFrameRate 進行動態調整,此技巧在遊戲及動畫設計中如果能應用得當,有時會取得意想不到的效果。

4)Silverlight中製作動畫常用的方法大致有5種:DispatcherTimer、Storyboard、Thread、CompositionTarget.Rendering、Storyboard as Trigger。5 methods to create game loop: which is the best?這篇文章中很詳細的列舉及討論了該5種方法在性能、穩定性等各方面的比較,結論加個人體會大致上是DispatcherTimer與Storyboard佔據了Top2的地位。下面是該作者的總結翻譯(原文在Demo的鏈接中,僅供大家參考,個人感覺有些評價並不太符合實際),爲大家今後製作Silverlight動畫提供更好的依據:

 

方法 優點 弊端 什麼時候使用合適?(建議) 什麼時候最好不要使用(建議)
DispatcherTimer
相對穩定
最小識別率約15毫秒(個人理解爲頻率過快將導致跳幀或無效,即極限爲15豪秒) 緩慢移動的物體,聯合Storyboard一同控制動畫 在處理一個移動非常快的物體對象時,建議使用Storyboard as Trigger或CompositionTarget.Rendering提高幀速率。
Storyboard 平滑的動畫 沒有複雜的運動效果,例如行星、遊戲等的無規則Path運動(這結論也太…… ^^||) 簡單的移動模式方面 如果想通過更多的後臺代碼去控制動畫,建議還是使用CompositionTarget.Rendering。(這建議真的很暈……)
Thread 基於線程,均衡的每幀運行。在多核中效果更好 在很短的間隔內不穩定(2幀間) 需要大量計算,耗CPU的處理 如果你的電腦只有1個CPU,或者需要更快的動畫效果,還是請選擇其他的方法
CompositionTarget.Rendering 非常穩定,保證會運行到位 無法進行細節控制,因爲頻率是固定的,基於畫面刷新觸發,公式:1000/<frames-per-secspecified-
in-html>
[msec]
複雜的邏輯,如遊戲中的一些循環等邏輯(原話看得不是很懂……) 一些瑣碎的處理,例如遊戲中的雲朵從左飄到右,則建議使用Storyboard代替。
Storyboard as Trigger 類似DispatcherTimer,在300FPS下運行流暢 和DispatcherTimer

三)源文件保護

第二節中我分析了幾種保護Silverlight源碼的方法,代碼混淆是最終解決方案。但隨着Silverlight應用越來越廣泛且豐富,以增強用戶體驗爲目標,我們通常會將圖片等素材從xap壓縮包中分離出來,作爲動態資源進行按需下載。然而這將直接導致所有素材裸露於Temporary Internet Files中,源碼保住了,但是又泄露了素材資源,結果is so bad。

解決方案:以下載圖片爲例,在Silverlight遊戲設計教程第九節結尾我曾詳細的講解了BitmapImage的諸多細節,將BitmapImage的CreateOptions屬性設定爲BitmapCreateOptions.None,圖片將分成兩份,一份存於內存中,一份存於Temporary Internet Files;然後再利用第二節方法一提到的禁止關鍵文件或文件夾頁面緩存,我們將讓用戶永遠也無法觸摸到Silverlight中的任何圖片素材,而所有資源素材一經下載後將永駐內存直至頁面關閉。不過副作用還是有的,沒了瀏覽器緩存,每次進入遊戲都需要重新下XAP及相關資源;圖片呈現方面也稍微有些延遲。當然了,每次2、3百K的XAP 按需獲取資源所增加的服務器流量負荷相對於完全泄露項目資源來說一毛九牛。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章