coco筆記:如何管好.net的內存

.net的性能瓶頸,毫無疑問是在內存管理上面。自動內存回收解決不了所有的問題,反而會製造性能問題。所以大批c++專家都不贊同在c++內部添加類似.net的內存管理機制,只是有保留的通過程序庫來支持相關技術。

java老愛說c/c++管不好內存,容易泄露。但是其實本質上還不是將本來該由終端程序員自己處理的事情,交給了框架開發人員來處理了。

既然都是程序員,憑什麼說你這些框架開發者就不會出現人爲錯誤?

他們是專家,對大部分菜鳥級別的程序員來說,這個策略有點幫助,這是當然。但是從根本上,交給框架開發人員處理是有侷限性的。他們無法預料到最終的應用程序有怎樣的需求,脫離了具體的開發環境,也就無法做出最體貼的解決方案出來。

因此,也不要認爲.net之類的內存管理必然就很先進,有這麼大的侷限性存在,還敢號稱什麼“無泄漏”?

內存泄漏是怎樣的概念?我想說說我的看法。

我認爲內存如果不在它該釋放的那一刻,到需要再度利用這段時間,做到平滑,就不能算是優秀的內存管理。

.net的管理機制是惰性的,非到迫不得已,都不會釋放掉,結果就把內存無端端的佔用掉了,系統可用內存無端端就少了一大截。

這種和泄漏也差不了多少,某種程度上甚至還更糟糕。比如你泄漏一整天,就幾兆,無傷大雅,但是你卻無端端佔用幾百兆的內存,這個對系統的性能影響更大。所謂的泄漏不泄漏,不是本質,本質是對系統的負擔有多大,內存管理機制有多高效。

有沒有辦法,讓我們對.net的內存管理更加主動?這就是這篇文章要探討的內容。

 

在開發過程中,性能問題往往出現在濫用框架功能上面。比如string不適合拼接字符串,程序員卻濫用了。諸如此類的,解決方案就是我們有能力去理解框架提供的內容和重新設計一個更加有效率的編碼。爲什麼說我們不能忘掉算法這些,原因就在此,框架的功能並不能適用在特定需求上面的,如果離開框架我們就無法工作,那樣做出來的產品往往就只是二三流水準。這些內容不需要很多,卻又必不可少。

這就是控制力的問題,如何做到更加細緻的控制,是關鍵時刻解決問題的制勝之道。在直路,賽車手和平民的區別也許相對來說不是很大,但是拐彎就體現真功夫。我們可能要花90%的力氣去做這10%的工作,才能保證軟件的品質。

如何提高我們對.net託管內存的控制?

一、理解.net的內存管理機制。

二、瞭解框架要求程序員負責的任務。

三、瞭解手動控制的手段。

 

以c#語言爲例。

析構函數如: ~類名() 默認是不自動生成的,也不能繼承。但是析構函數並不管理內存,.net把內存作爲資源的獨立部分來管理,內存自動管理,其餘資源依賴程序員自己通過析構函數等手段來管理。

因爲內存是自動管理的,程序員只需要瞭解第三點:手動控制的手段。

System.GC.Collect() 強制啓動內存垃圾回收程序。

第二個問題是除內存之外的其餘資源如何管理。

.net 把任何實現了析構函數的對象,加入一個待清理隊列中,這個隊列會去調用析構函數,這個時候就能釋放資源了。

因此,只要實現了析構函數,然後把釋放資源的代碼放在析構函數內部,就能交由.net處理餘下事項,你也不需要擔心自己忘了清理。

如果我們想要他在立即執行這個操作,可以調用System.GC.Collect()來啓動。

問題是,.net實現這個機制的代價是很高的,如果我們又要釋放資源,又不想影響效率,而且又擔心我們會忘了釋放資源,可以採取以下設計模式:

1.實現一個釋放資源的函數。方便我們手工調用。

2.在析構函數中調用這個函數。

3.釋放資源的函數中調用System.GC.SupressFinalize(),就會把對象從.net的待清理隊列中釋放出來,這樣.net就不會啓動釋放機制了。

4.必須有一個標誌來判斷是否已經把資源釋放了,避免重複釋放資源。

5.必須有一個標誌來判斷是否需要調用System.GC.SupressFinalize()。如果程序員忘了手動清理,而是.net自身通過調用析構函數去清理的,那把對象從待清理隊列中釋放已經是沒有意義的事情了。

可見,如果要高效,還是免不了要程序員自己記得手工釋放。

 

以上是管理內存和其餘資源的方式,至於如何運用,我個人的看法是,只要資源沒有利用價值了,就應該儘快釋放掉,而不是等緩慢的.net回收機制。


轉載:http://www.cnblogs.com/Nobel/archive/2010/12/19/1910626.html

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