.NET性能优化-使用RecyclableMemoryStream

吕宣
2023-12-01

.NET性能优化-使用RecyclableMemoryStream替代MemoryStream - 非常男人网

提到MemoryStream大家可能都不陌生,在编写代码中或多或少有使用过;比如Json序列化反序列化、导出PDF/Excel/Word、进行图片或者文字处理等场景。但是如果使用它高频、大数据量处理这些数据,就存在一些性能陷阱。

今天给大家带来的这个优化技巧其实就是池化MemoryStream的版本RecyclableMemoryStream,它通过池化MemoryStream底层buffer来降低内存占用率、GC暂停时间和GC次数达到提升性能目的。

它的开源库地址如下链接:

 

https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream

使用它也非常简单,直接安装对应的Nuget包即可,目前最新版本是2.2.1版本。

 

// 命令行安装

dotnet add package Microsoft.IO.RecyclableMemoryStream --version 2.2.1

// csproj 安装<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.2.1" />

然后创建一个RecyclableMemoryStreamManager对象,即可使用它的GetStream方法来获取一个池化的流,当然使用完这个流以后需要调用Dispose方法将其归还到池中,也可以使用using模式来释放。

 
  1. class Program
  2. {
  3. private static readonly RecyclableMemoryStreamManager manager = new RecyclableMemoryStreamManager();
  4. static void Main(string[] args)
  5. {
  6. var sourceBuffer = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
  7. using (var stream = manager.GetStream())
  8. {
  9. stream.Write(sourceBuffer, 0, sourceBuffer.Length);
  10. }
  11. }
  12. }

在创建RecyclableMemoryStreamManagerGetStream时有很多选项,可以设置底层buffer的大小、为流进行命名隔离等精细化的选项,这些大家可以看官方文档了解,本文不再赘述。

性能比较

为了直观的比较性能,我构建了一个Benchmark,这个基准测试分别使用MemoryStreamRecyclableMemoryStream实现数据缓冲的功能,下面是测试代码:

 
  1. public class BenchmarkRecyclableMemoryStream
  2. {
  3. // 生成随机数
  4. private static readonly Random Random = new(1024);
  5. // 填充的数据
  6. private static readonly byte[] Data = Enumerable.Range(0, 81920).Select(d => (byte) d).ToArray();
  7. // 每次随机填充
  8. private static readonly int[] DataLength = Enumerable.Range(0, 1000).Select(d => Random.Next(10240, 81920)).ToArray();
  9. // RecyclableManager
  10. private static readonly RecyclableMemoryStreamManager Manager = new();
  11. [Benchmark(Baseline = true)]
  12. public long UseMemoryStream()
  13. {
  14. var sum = 0L;
  15. for (int i = 0; i < DataLength.Length; i++)
  16. {
  17. using var stream = new MemoryStream();
  18. stream.Write(Data, 0, DataLength[i]);
  19. sum += stream.Length;
  20. }
  21. return sum;
  22. }
  23. [Benchmark]
  24. public long UseRecyclableMemoryStream()
  25. {
  26. var sum = 0L;
  27. for (int i = 0; i < DataLength.Length; i++)
  28. {
  29. using var stream = Manager.GetStream();
  30. stream.Write(Data, 0, DataLength[i]);
  31. sum += stream.Length;
  32. }
  33. return sum;
  34. }
  35. }

下方是测试的结果,可以看到使用RecyclableMemoryStream比直接使用MemoryStream在内存和速度上有很大的优势。

执行效率快51%
内存分配要低99.4%

 类似资料: