.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
模式来释放。
class Program
{
private static readonly RecyclableMemoryStreamManager manager = new RecyclableMemoryStreamManager();
static void Main(string[] args)
{
var sourceBuffer = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
using (var stream = manager.GetStream())
{
stream.Write(sourceBuffer, 0, sourceBuffer.Length);
}
}
}
在创建RecyclableMemoryStreamManager
和GetStream
时有很多选项,可以设置底层buffer的大小、为流进行命名隔离等精细化的选项,这些大家可以看官方文档了解,本文不再赘述。
为了直观的比较性能,我构建了一个Benchmark,这个基准测试分别使用MemoryStream
和RecyclableMemoryStream
实现数据缓冲的功能,下面是测试代码:
public class BenchmarkRecyclableMemoryStream
{
// 生成随机数
private static readonly Random Random = new(1024);
// 填充的数据
private static readonly byte[] Data = Enumerable.Range(0, 81920).Select(d => (byte) d).ToArray();
// 每次随机填充
private static readonly int[] DataLength = Enumerable.Range(0, 1000).Select(d => Random.Next(10240, 81920)).ToArray();
// RecyclableManager
private static readonly RecyclableMemoryStreamManager Manager = new();
[Benchmark(Baseline = true)]
public long UseMemoryStream()
{
var sum = 0L;
for (int i = 0; i < DataLength.Length; i++)
{
using var stream = new MemoryStream();
stream.Write(Data, 0, DataLength[i]);
sum += stream.Length;
}
return sum;
}
[Benchmark]
public long UseRecyclableMemoryStream()
{
var sum = 0L;
for (int i = 0; i < DataLength.Length; i++)
{
using var stream = Manager.GetStream();
stream.Write(Data, 0, DataLength[i]);
sum += stream.Length;
}
return sum;
}
}
下方是测试的结果,可以看到使用RecyclableMemoryStream
比直接使用MemoryStream
在内存和速度上有很大的优势。
执行效率快51%
内存分配要低99.4%