2014-01-08 44 views
0

現在我開始大量使用緩衝區的典型應用程序的工作..我很驚訝,我無法找到有關此主題的良好的明確指南。真正的緩衝區使用指導

我有幾個問題。

1)何時我更喜歡在託管內存的非託管堆內存中使用緩衝區? 我知道對象分配在.net上更快,然後對非託管堆和對象的破壞在.NET上因爲GC開銷而要昂貴得多,所以我認爲使用非託管對象會快一點。什麼時候應該使用固定{}和何時Marshal.AllocHGlobal()?

2)據我所知,如果緩衝可能可以在一段時間後重新使用(基於用戶操作),那麼在.net中使用託管和非託管緩衝區的周引用會更有效,不是嗎?

回答

2

嘗試使用本機「緩衝區」手動管理內存分配對於.NET來說最多是困難的。您不能將託管類型分配到非託管緩衝區,因此它們只能用於結構化數據,在這種情況下,與簡單的託管數組(它將連續存儲在內存中)幾乎沒有什麼優勢。

通常,嘗試管理對象分配和放開的方式通常是一種更好的方法,並嘗試根據需要手動重用它們(如果且僅當內存壓力對您而言是個問題時) 。

至於一些特定點:

我知道,對象分配是基於.NET更快然後在非託管堆和對象的破壞是因爲GC開銷.NET貴得多,所以我認爲使用非託管服務會快一點。

我認爲你在這裏的假設有點有缺陷。在分配點分配對象時,.NET中的對象分配通常更快,因爲CLR可能具有可以使用的預分配內存。對象「銷燬」在.NET上也更快,不過由於GC的原因,可能會更高一些(儘管並非總是如此),但延遲成本仍然存在。這裏有很多因素,主要集中在對象生命週期 - 如果您允許將對象升級到Gen1或特別是Gen2,那麼由於GC壓縮成本可能更高,事情可能難以跟蹤和測量。

什麼時候應該使用固定{}和何時Marshal.AllocHGlobal()?

一般來說,你會(很)很少在C#中使用。通常情況下,您最好不要固定內存,並允許GC正確執行其工作,這反過來會導致整體上更好的GC啓發式。

2)以我的理解是更有效的使用一週參考在.NET託管和非託管的緩衝區,如果緩衝可能一段時間後(根據和用戶操作)可重複使用,是不是?

不一定。重複使用對象並使它們長時間不活動也存在一些嚴重的缺陷。這可能會保證內存將被升級到Gen2,這可能會使生活變得更糟,而不是更好。

通常情況下,我的建議是相信系統,但是隨時測量。當且僅當您發現真正的問題時,幾乎總是有辦法解決那些特定問題(不訴諸非託管或手動管理內存緩衝區)。處理原始內存應該是處理託管代碼庫時的絕對最後手段。

+0

當我需要將緩衝區傳遞給本地API時,最好是將託管的固定對象或堆上的非託管緩衝區傳遞給它? (例如我需要用零填充文件的緩衝區) –

+0

@BransDs對於您的示例,我只是使用託管API來填充文件。一般來說,固定和傳遞固定指針可以避免不必要的複製。 –