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

相关推荐
plainGeekDev1 小时前
ButterKnife → ViewBinding
android·java·kotlin
罗西的思考13 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队16 小时前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
像我这样帅的人丶你还17 小时前
Java 后端详解(四):分页与搜索
java·javascript·后端
她的男孩17 小时前
数据权限为什么不能只靠注解?Forge 的 Mapper 层 SQL 改写源码拆解
java·后端·架构
tntxia18 小时前
Mybatis的日志输入
java
亦暖筑序19 小时前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
用户298698530141 天前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao1 天前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿1 天前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试