介绍
RecyclableBuffer 是一个高性能的缓冲区管理库,它使用 ArrayPool<byte>
实现可回收内存段。该系统提供了两个互补的缓冲区写入器实现:一个针对连续内存方案进行了优化,另一个针对多段数据处理进行了优化。
组件
SingleSegmentBufferWriter
SingleSegmentBufferWriter 提供一种在单个连续内存段中维护数据的实现。与分段方法不同,此编写器确保所有写入的数据保留在一个内存块中,非常适合需要连续数据访问或与需要单个内存区域的 API 集成的场景。
主要特征
- 实现接口
IBufferWriter<byte>
- 在单个连续内存段中维护数据
- 在超出容量时提供自动缓冲区大小调整
- 集成以实现高效的内存管理
ArrayPool<byte>
- 支持Stream接口写入和Stream接口读取
MultipleSegmentBufferWriter
MultipleSegmentBufferWriter 提供高性能缓冲区编写器实现,用于管理数据可能超过单个缓冲区容量的方案中的多个内存段。与在连续内存上运行的 SingleSegmentBufferWriter 不同,此类根据需要自动分配和链接多个缓冲区段,将它们呈现为统一的 ReadOnlySequence<byte>
以供使用。
主要特征
- 实现接口
IBufferWriter<byte>
- 在多内存段中维护数据
- 在超出容量时提供自动增加内存段
- 集成以实现高效的内存管理
ByteArrayPool
- 支持Stream接口写入和Stream接口读取
高效的缓冲区池
ByteArrayPool 根据请求的最小长度实现双路径分配策略,正常情况下都使用自维护的ByteArrayBucket,意外情况下转为使用ArrayPool<byte>.Shared
池,从下面的第一个 Benchmark 中要可以看出池的表现稳定。

Benchmark
大部分情况下 RecyclableBuffer 的 Benchmark 成绩 略微优于 RecyclableMemoryStream。
内存申请Benchmark
这里测试了三种 SizeHint 值,0B 值的绝大多数场景、8KB 的手动申请场景和 128KB+1B 的超过单个缓冲区大小场景。可以看到 RecyclableMemoryStream 在 SizeHint 超过其默认的单个缓冲区大小(128KB)时受到了性能处罚,请注意除非用户是新手,否则谁也不会指定这么大的 SizeHint 值。
Method | SizeHint | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|---|
SingleSegmentBufferWriter | 0 | 104.9 ns | 2.05 ns | 2.28 ns | 0.80 | 0.03 | 0.0191 | - | - | 80 B | 0.45 |
MultipleSegmentBufferWriter | 0 | 131.7 ns | 2.62 ns | 4.08 ns | 1.00 | 0.04 | 0.0420 | - | - | 176 B | 1.00 |
RecyclableMemoryStream | 0 | 315.5 ns | 5.55 ns | 4.64 ns | 2.40 | 0.08 | 0.0668 | - | - | 280 B | 1.59 |
SingleSegmentBufferWriter | 8192 | 106.0 ns | 2.08 ns | 2.23 ns | 0.81 | 0.02 | 0.0191 | - | - | 80 B | 0.45 |
MultipleSegmentBufferWriter | 8192 | 130.6 ns | 2.51 ns | 1.96 ns | 1.00 | 0.02 | 0.0420 | - | - | 176 B | 1.00 |
RecyclableMemoryStream | 8192 | 309.0 ns | 6.14 ns | 5.45 ns | 2.37 | 0.05 | 0.0668 | - | - | 280 B | 1.59 |
SingleSegmentBufferWriter | 131073 | 146.0 ns | 2.93 ns | 2.88 ns | 1.05 | 0.03 | 0.0286 | - | - | 120 B | 0.68 |
MultipleSegmentBufferWriter | 131073 | 139.2 ns | 2.75 ns | 3.76 ns | 1.00 | 0.04 | 0.0420 | - | - | 176 B | 1.00 |
RecyclableMemoryStream | 131073 | 40,636.0 ns | 397.91 ns | 332.27 ns | 292.08 | 8.09 | 333.3130 | 333.3130 | 333.3130 | 1049020 B | 5,960.34 |
内存写入和归还Benchmark
这里测试了三种 BufferSize 值,1KB、8KB 和 128KB+1B 的超过单个缓冲区大小场景。可以看到 SingleSegmentBufferWriter 在 BufferSize 超过其默认的单个缓冲区大小(128KB)时受到了复制的性能处罚。
Method | BufferSize | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
SingleSegmentBufferWriter | 1024 | 132.5 ns | 2.65 ns | 3.15 ns | 0.89 | 0.03 | 0.0191 | 80 B | 0.45 |
MultipleSegmentBufferWriter | 1024 | 149.7 ns | 3.02 ns | 4.70 ns | 1.00 | 0.04 | 0.0420 | 176 B | 1.00 |
RecyclableMemoryStream | 1024 | 405.3 ns | 16.78 ns | 47.89 ns | 2.71 | 0.33 | 0.0668 | 280 B | 1.59 |
SingleSegmentBufferWriter | 8192 | 224.3 ns | 4.51 ns | 8.90 ns | 0.84 | 0.05 | 0.0191 | 80 B | 0.45 |
MultipleSegmentBufferWriter | 8192 | 267.4 ns | 5.38 ns | 11.81 ns | 1.00 | 0.06 | 0.0420 | 176 B | 1.00 |
RecyclableMemoryStream | 8192 | 467.6 ns | 9.05 ns | 11.44 ns | 1.75 | 0.09 | 0.0668 | 280 B | 1.59 |
SingleSegmentBufferWriter | 131073 | 9,217.2 ns | 270.79 ns | 768.19 ns | 1.97 | 0.18 | 0.0153 | 126 B | 0.58 |
MultipleSegmentBufferWriter | 131073 | 4,675.8 ns | 91.93 ns | 161.00 ns | 1.00 | 0.05 | 0.0458 | 216 B | 1.00 |
RecyclableMemoryStream | 131073 | 5,555.9 ns | 194.58 ns | 570.67 ns | 1.19 | 0.13 | 0.0687 | 312 B | 1.44 |
总结
如果你的 API 集成的场景需要单个内存区域,那就使用 SingleSegmentBufferWriter,但需要注意提供合适的初始缓冲区大小防止扩容而Copy;
其它场景,使用 MultipleSegmentBufferWriter 即可。