介绍
RecyclableBuffer 是一个高性能的缓冲区管理库,它使用 ArrayPool 实现可回收内存段。该系统提供了两个互补的缓冲区写入器实现:一个针对连续内存方案进行了优化,另一个针对多段数据处理进行了优化。
组件
SingleSegmentBufferWriter
SingleSegmentBufferWriter 提供一种在单个连续内存段中维护数据的实现。与分段方法不同,此编写器确保所有写入的数据保留在一个内存块中,非常适合需要连续数据访问或与需要单个内存区域的 API 集成的场景。
主要特征
- 实现接口 IBufferWriter
- 在单个连续内存段中维护数据
- 在超出容量时提供自动缓冲区大小调整
- 集成以实现高效的内存管理 ArrayPool
- 支持Stream接口写入和Stream接口读取
MultipleSegmentBufferWriter
MultipleSegmentBufferWriter 提供高性能缓冲区编写器实现,用于管理数据可能超过单个缓冲区容量的方案中的多个内存段。与在连续内存上运行的 SingleSegmentBufferWriter 不同,此类根据需要自动分配和链接多个缓冲区段,将它们呈现为统一的 ReadOnlySequence 以供使用。
主要特征
- 实现接口 IBufferWriter
- 在多内存段中维护数据
- 在超出容量时提供自动增加内存段
- 集成以实现高效的内存管理 ByteArrayPool
- 支持Stream接口写入和Stream接口读取
高效的缓冲区池
ByteArrayPool 根据请求的最小长度实现双路径分配策略,正常情况下都使用自维护的ByteArrayBucket,意外情况下转为使用ArrayPool.Shared池,从下面的第一个 Benchmark 中要可以看出池的表现稳定。
Benchmark
大部分情况下 RecyclableBuffer 的 Benchmark 成绩 略微优于 RecyclableMemoryStream。
内存申请Benchmark
这里测试了三种 SizeHint 值,0B 值的绝大多数场景、8KB 的手动申请场景和 128KB+1B 的超过单个缓冲区大小场景。可以看到 RecyclableMemoryStream 在 SizeHint 超过其默认的单个缓冲区大小(128KB)时受到了性能处罚,请注意除非用户是新手,否则谁也不会指定这么大的 SizeHint 值。
MethodSizeHintMeanErrorStdDevRatioRatioSDGen0Gen1Gen2AllocatedAlloc RatioSingleSegmentBufferWriter0104.9 ns2.05 ns2.28 ns0.800.030.0191--80 B0.45MultipleSegmentBufferWriter0131.7 ns2.62 ns4.08 ns1.000.040.0420--176 B1.00RecyclableMemoryStream0315.5 ns5.55 ns4.64 ns2.400.080.0668--280 B1.59SingleSegmentBufferWriter8192106.0 ns2.08 ns2.23 ns0.810.020.0191--80 B0.45MultipleSegmentBufferWriter8192130.6 ns2.51 ns1.96 ns1.000.020.0420--176 B1.00RecyclableMemoryStream8192309.0 ns6.14 ns5.45 ns2.370.050.0668--280 B1.59SingleSegmentBufferWriter131073146.0 ns2.93 ns2.88 ns1.050.030.0286--120 B0.68MultipleSegmentBufferWriter131073139.2 ns2.75 ns3.76 ns1.000.040.0420--176 B1.00RecyclableMemoryStream13107340,636.0 ns397.91 ns332.27 ns292.088.09333.3130333.3130333.31301049020 B5,960.34内存写入和归还Benchmark
这里测试了三种 BufferSize 值,1KB、8KB 和 128KB+1B 的超过单个缓冲区大小场景。可以看到 SingleSegmentBufferWriter 在 BufferSize 超过其默认的单个缓冲区大小(128KB)时受到了复制的性能处罚。
MethodBufferSizeMeanErrorStdDevRatioRatioSDGen0AllocatedAlloc RatioSingleSegmentBufferWriter1024132.5 ns2.65 ns3.15 ns0.890.030.019180 B0.45MultipleSegmentBufferWriter1024149.7 ns3.02 ns4.70 ns1.000.040.0420176 B1.00RecyclableMemoryStream1024405.3 ns16.78 ns47.89 ns2.710.330.0668280 B1.59SingleSegmentBufferWriter8192224.3 ns4.51 ns8.90 ns0.840.050.019180 B0.45MultipleSegmentBufferWriter8192267.4 ns5.38 ns11.81 ns1.000.060.0420176 B1.00RecyclableMemoryStream8192467.6 ns9.05 ns11.44 ns1.750.090.0668280 B1.59SingleSegmentBufferWriter1310739,217.2 ns270.79 ns768.19 ns1.970.180.0153126 B0.58MultipleSegmentBufferWriter1310734,675.8 ns91.93 ns161.00 ns1.000.050.0458216 B1.00RecyclableMemoryStream1310735,555.9 ns194.58 ns570.67 ns1.190.130.0687312 B1.44总结
如果你的 API 集成的场景需要单个内存区域,那就使用 SingleSegmentBufferWriter,但需要注意提供合适的初始缓冲区大小防止扩容而Copy;
其它场景,使用 MultipleSegmentBufferWriter 即可。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |