NET性能优化-使用RecyclableBuffer取代RecyclableMemoryStream

组件#

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,但需要注意提供合适的初始缓冲区大小防止

相关推荐
iAkuya2 分钟前
(leetcode)力扣100 61分割回文串(回溯,动归)
算法·leetcode·职场和发展
梵刹古音5 分钟前
【C语言】 指针与数据结构操作
c语言·数据结构·算法
VT.馒头11 分钟前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript
Anastasiozzzz44 分钟前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
骇客野人1 小时前
通过脚本推送Docker镜像
java·docker·容器
程序猿追1 小时前
深度解析CANN ops-nn仓库 神经网络算子的性能优化与实践
人工智能·神经网络·性能优化
铁蛋AI编程实战1 小时前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python
晚霞的不甘1 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
SunnyDays10111 小时前
使用 Java 冻结 Excel 行和列:完整指南
java·冻结excel行和列
摇滚侠1 小时前
在 SpringBoot 项目中,开发工具使用 IDEA,.idea 目录下的文件需要提交吗
java·spring boot·intellij-idea