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

相关推荐
国科安芯2 小时前
ASP3605电源芯片的性能优化与改进思路
网络·单片机·嵌入式硬件·安全·性能优化
TechMix2 小时前
【性能优化】帧率优化方法:第一步——量化
性能优化
lang201509282 小时前
MySQL 8.0性能优化终极指南
数据库·mysql·性能优化
kfepiza2 小时前
CAS (Compare and Swap) 笔记251007
java·算法
kfepiza3 小时前
Java的`volatile`关键字 笔记251007
java
风雨同舟的代码笔记3 小时前
JDK1.8 String类源码学习
java
苹果醋33 小时前
数据结构其一 线性表
java·运维·spring boot·mysql·nginx
华仔啊3 小时前
前后端防重复提交的 6 种落地实现:从按钮禁用到 AOP 全自动防护
java·后端
墨染点香3 小时前
LeetCode 刷题【103. 二叉树的锯齿形层序遍历、104. 二叉树的最大深度、105. 从前序与中序遍历序列构造二叉树】
算法·leetcode·职场和发展