淺析池化對象 RecyclableMemoryStream 在 .netcore 中的使用
本文轉載自微信公眾號「碼農讀書」,作者碼農讀書。轉載本文請聯(lián)系碼農讀書公眾號。
Microsoft.IO.RecyclableMemoryStream 是一個被設計為專門用于提高 Stream 操作的高性能類庫,意思很明顯,專用于取代 MemoryStream 而生,RecyclableMemoryStream 可以最大限度的避免 Stream 操作在 GC 上的 LOH (大對象堆)的分配和內存碎片,泄露等煩人的問題,這篇文章我們將會討論 Microsoft.IO.RecyclableMemoryStream 及如何在 .NET Core 應用程序中提升性能。
RecyclableMemoryStream 的價值
RecyclableMemoryStream 大體上提供了如下四點價值。
- 使用緩沖池避免 LOH 分配。
- 大大的減少生成到2代堆的可能,相對減少了 GC 回收時造成的線程停滯時間。
- 避免了內存碎片和內存泄漏。
- 提供了用于跟蹤和分析性能的度量值。
RecyclableMemoryStream 的原理
RecyclableMemoryStream 在2代堆上存儲了一個用于流的大型緩沖區(qū),并能夠確保這個緩沖區(qū)在進程的生命周期內一直存在,這就確保了GC不會頻繁的出現全量回收,同時 RecyclableMemoryStreamManager 類維護了兩類緩沖池。
- 小型緩沖池 常用于讀寫操作,每一個小池子大小為 128k。
- 大型緩沖池 常用于當有連續(xù)緩沖的場景下使用,每一個大池子大小為 1MB。
值得注意的是,大型緩沖池的擴容又分為 線性增長 和 指數型增長,可以看出內存可被高效的反復使用并且對調用者還是無感知的,這就是為什么 RecyclableMemoryStream 比 MemoryStream 更好更高效的原因。
當調用 GetBuffer() 方法時,小緩沖區(qū)將會轉換為一個大的連續(xù)緩沖區(qū),如下代碼所示:
- var buffer = recyclableMemoryStreamManager.GetStream().GetBuffer();
安裝 RecyclableMemoryStream
你可以通過 Nuget 可視化界面安裝 Microsoft.IO.RecyclableMemoryStream 或者通過 NuGet package manager console window 執(zhí)行如下命令。
- Install-Package Microsoft.IO.RecyclableMemoryStream
使用 RecyclableMemoryStream
安裝好之后,接下來我們通過 RecyclableMemoryStream 將數據寫入到 MemoryStream 中,值得注意的是,RecyclableMemoryStreamManager.GetStream() 方法返回的是 MemoryStream 實例。
- class Program
- {
- private static readonly RecyclableMemoryStreamManager recyclableMemoryStreamManager = new RecyclableMemoryStreamManager();
- static void Main(string[] args)
- {
- string data = "This is a sample text message.";
- var buffer = Encoding.ASCII.GetBytes(data);
- using (var memoryStream = recyclableMemoryStreamManager.GetStream())
- {
- memoryStream.Write(buffer, 0, buffer.Length);
- }
- Console.ReadKey();
- }
- }
上面的代碼還有一點要注意,我將 RecyclableMemoryStreamManager 靜態(tài)化了,意味著它只需要定義一次就ok了,還有一點你可以對 MemoryStream 進行標記,方便后續(xù)持續(xù)跟蹤,如下代碼所示:
- using (var memoryStream = recyclableMemoryStreamManager.GetStream("High_Performance_Stream_Demo.Program.Main"))
- {
- memoryStream.Write(buffer, 0, buffer.Length);
- }
對 MemoryStream Pool 精細化配置
如果你想對 MemoryStream Pool 做更精細化的配置,可以在 RecyclableMemoryStreamManager 實例上進行配置,如下代碼所示:
- int blockSize = 1024;
- int largeBufferMultiple = 1024 * 1024;
- int maximumBufferSize = 16 * largeBufferMultiple;
- int maximumFreeLargePoolBytes = maximumBufferSize * 4;
- int maximumFreeSmallPoolBytes = 250 * blockSize;
- var recyclableMemoryStreamManager = new RecyclableMemoryStreamManager(blockSize, largeBufferMultiple, maximumBufferSize);
- recyclableMemoryStreamManager.AggressiveBufferReturn = true;
- recyclableMemoryStreamManager.GenerateCallStacks = true;
- recyclableMemoryStreamManager.MaximumFreeLargePoolBytes = maximumFreeLargePoolBytes;
- recyclableMemoryStreamManager.MaximumFreeSmallPoolBytes = maximumFreeSmallPoolBytes;
RecyclableMemoryStream 最佳實踐
內存碎片會影響到程序的性能,而且LOH獨有的鏈式管理也非常容易產生內存碎片,下面是使用 RecyclableMemoryStream 應該遵循的一些經驗法則。
- 根據你的業(yè)務場景設置合適的 blockSize, largeBufferMultiple, maxBufferSize, MaximumFreeLargePoolBytes, MaximumFreeSmallPoolBytes 值。
- 當使用完 Stream 對象時一定要速速關閉。
- 永遠不要調用 ToArray() 方法。
- 盡可能避免調用 GetBuffer() 方法。
Microsoft.IO.RecyclableMemoryStream 是 MemoryStream 的池化對象,它技巧性的減少了 GC 的負載并減少了 LOH 的大對象分配,自然就提高了應用程序的性能,不僅避免了內存碎片和內存泄漏還提供了用于跟蹤性能的指標。
譯文鏈接:https://www.infoworld.com/article/3597060/how-to-use-recyclablememorystream-in-net-core.html