dotnet高性能buffer
1 前言
我曾经写过《杂谈.netcore的Buffer相关新类型》的博客,简单介绍过BinaryPrimitives、Span<>,Memory<>,ArrayPool<>,Memorypool<>这些基础类型,在实际项目中,我们更需要的是更上层的高效缓冲区申请、buffer写入、buffer读取功能。本文将介绍如何利用这些基础类型,封装成易于使用的buffer相关操作类,这些类的源代码在MemoryExtensions库里。
2 buffer知识
buffer的申请
通过经验与实验数据,根据不同场景与buffer大小,选择合适的申请方式。
申请式 | 特点 | 局限 |
---|---|---|
stackalloc byte | 非常快速 | 堆栈上分配内存块,容量小且在方法返回时缓冲区丢弃 |
new byte[] | 当小于1KB时速度快 | 频繁创建导致内存碎片,GC压力大 |
ArrayPool.Rent | 适合大的缓冲区租赁,几乎无内存分配 | 缓冲区小于1KB时,租赁不如new来得快 |
IBufferWriter接口
此接口支持获取缓冲区的写入Span或GetMemory给外部直接写入数据,写入完成之后调用Advance(int)方法,告诉writer实际的写入大小。
我们来对比一下MemoryStream的Write()方法,比如要写一个int类型的值,我们不得不将int转为4字节的byte[],然后传byte[]到Write()方法。这个4字节的byte[]是一个副作用,它的存在原于外部无法获取和扩大MemoryStream的缓冲区。
3 BufferWriter的实现
根据“buffer的申请”几种方式,我们实现多种不同的BufferWriter。
RecyclableBufferWriter
可回收的自动扩容BufferWriter,适合于大的缓冲区的场景。它的缓冲区通过ArrayPool来租赁,用完之后,要Dispose()归还到ArrayPool。优点是内存分配少,缺点是租赁比直接创建小的缓冲区还要慢。
var writer = new RecyclableBufferWriter<byte>(4);
writer.Write((byte)1);
writer.Write(new byte[] { 2, 3, 4 });
writer.WriteBigEndian(int.MaxValue);
var writtern = writer.WrittenSpan; // 1,2,3,4,127,255,255,255
// return the buffer to pool
writer.Dispose();
ResizableBufferWriter
自动扩容的BufferWriter,适合小的动态缓冲区的场景。它的冲区通过new Array来创建,通过Array.Resize扩容。优点是cpu性能好,缺点是内存分配高。
var writer = new ResizableBufferWriter<byte>(4);
writer.Write((byte)1);
writer.Write(new byte[] { 2, 3, 4 });
writer.WriteBigEndian(int.MaxValue);
var writtern = writer.WrittenSpan; // 1,2,3,4,127,255,255,255
FixedBufferWriter
固定大小缓冲区,就是我们自己new的Array,包装为IBufferWriter对象。
var array = new byte[16];
var writer = array.CreateWriter();
writer.WriteBigEndian(18);
writer.WriteBigEndian(2.01f);
4 IBufferWriter的扩展
经常会遇到将int、double等诸多数字类型写入IBufferWriter的场景,期间还涉及平台的BigEndian或LittleEndian,我们给IBufferWriter<byte>
编写重载的扩展方法。
方法 | 说明 |
---|---|
WriteBigEndian(this IBufferWriter, short) | short |
WriteBigEndian(this IBufferWriter, int) | int |
WriteBigEndian(this IBufferWriter, long) | long |
WriteBigEndian(this IBufferWriter, ushort) | ushort |
WriteBigEndian(this IBufferWriter, uint) | uint |
WriteBigEndian(this IBufferWriter, ulong) | ulong |
WriteBigEndian(this IBufferWriter, float) | float |
WriteBigEndian(this IBufferWriter, double) | double |
WriteLittleEndian(this IBufferWriter, short) | short |
WriteLittleEndian(this IBufferWriter, int) | int |
WriteLittleEndian(this IBufferWriter, long) | long |
WriteLittleEndian(this IBufferWriter, ushort) | ushort |
WriteLittleEndian(this IBufferWriter, uint) | uint |
WriteLittleEndian(this IBufferWriter, ulong) | ulong |
WriteLittleEndian(this IBufferWriter, float) | float |
WriteLittleEndian(this IBufferWriter, double) | double |
5 ref BufferReader
同样的,我们也经常遇到从缓冲区中读取为int、double等诸多数字类型的场景,所以也需要设计一个高效的BufferReader。
public ref struct BufferReader
{
/// <summary>
/// 未读取的数据
/// </summary>
private ReadOnlySpan<byte> span;
}
给它设计ReadLittleEndian和ReadBigEndian相关Api
方法 | 说明 |
---|---|
ReadBigEndian(out short) | short |
ReadBigEndian(out int) | int |
ReadBigEndian(out long) | long |
ReadBigEndian(out ushort) | ushort |
ReadBigEndian(out uint) | uint |
ReadBigEndian(out ulong) | ulong |
ReadBigEndian(out float) | float |
ReadBigEndian(out double) | double |
ReadLittleEndian(out short) | short |
ReadLittleEndian(out int) | int |
ReadLittleEndian(out long) | long |
ReadLittleEndian(out ushort) | ushort |
ReadLittleEndian(out uint) | uint |
ReadLittleEndian(out ulong) | ulong |
ReadLittleEndian(out float) | float |
ReadLittleEndian(out double) | double |
6 关于MemoryExtensions库
本文提到的这些类或结构体,在MemoryExtensions库里都有实现,可以直接使用,其中BufferWriter技术已经在WebApiClient里大量应用。
dotnet高性能buffer的更多相关文章
- [2018-11-03]2018年10月28日宁波dotnet社区活动回顾及下次活动预告
离上次活动,有半年了,汗.之后尽量保证每月一次,以组织为主,多邀请嘉宾来分享. 本次活动不足之处 人手不足:由于活动组织事项受限于人手(目前就我一个,这次活动前后我又应邀给大红鹰学院应届生介绍dotn ...
- 开源Influxdb2高性能客户端
前言 最近我在了解时序数据库Influxdb 2.x版本,体验一翻之后,感觉官方的出品的.net客户端还有很多优化的地方,于是闭关几天,不吃不喝,将老夫多年练就的高性能网络通讯与高性能Buffer操作 ...
- .NET 2.0 参考源码索引
http://www.projky.com/dotnet/2.0/Microsoft/CSharp/csharpcodeprovider.cs.htmlhttp://www.projky.com/do ...
- 线程安全使用(四) [.NET] 简单接入微信公众号开发:实现自动回复 [C#]C#中字符串的操作 自行实现比dotcore/dotnet更方便更高性能的对象二进制序列化 自已动手做高性能消息队列 自行实现高性能MVC WebAPI 面试题随笔 字符串反转
线程安全使用(四) 这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来. 这里主要讲解下CancellationT ...
- 使用Ring Buffer构建高性能的文件写入程序
最近常收到SOD框架的朋友报告的SOD的SQL日志功能报错:文件句柄丢失.经过分析得知,这些朋友使用SOD框架开发了访问量比较大的系统,由于忘记关闭SQL日志功能所以出现了很高频率的日志写入操作,从而 ...
- dotnet core 使用 MongoDB 进行高性能Nosql数据库操作
好久没有写过Blog, 每天看着开源的Java社区流口水, 心里满不是滋味. 终于等到了今年六月份 dotnet core 的正式发布, 看着dotnet 社区也一步一步走向繁荣, 一片蒸蒸日上的大好 ...
- Python使用Zero-Copy和Buffer Protocol实现高性能编程
无论你程序是做什么的,它经常都需要处理大量的数据.这些数据大部分表现形式为strings(字符串).然而,当你对字符串大批量的拷贝,切片和修改操作时是相当低效的.为什么? 让我们假设一个读取二进制数据 ...
- Netty使用Google Protocol Buffer完成服务器高性能数据传输
一.什么是Google Protocol Buffer(protobuf官方网站) 下面是官网给的解释: Protocol buffers are a language-neutral, platfo ...
- DotNet 资源大全中文版,内容包括:编译器、压缩、应用框架、应用模板、加密、数据库、反编译、IDE、日志、风格指南等
DotNet 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-dotnet 是由 quozd 发起和维护.内容包括:编译器. ...
随机推荐
- 题解 CF1375E Inversion SwapSort
蒟蒻语 这题是真的奇妙... 想了好久才想明白. 蒟蒻解 考虑冒泡排序是怎样的. 对于相邻的两个数 \(a_i, a_{i+1}\),如果 \(a_i>a_{i+1}\) 那么就交换两个数. 总 ...
- CSP-S2020 DP专项训练
前言 \(\text{CPS-S2020}\) 已然临近,而 \(\text{DP}\) 作为联赛中的常考内容,是必不可少的复习要点,现根据教练和个人刷题,整理部分好题如下(其实基本上是直接搬--). ...
- 题解-Ehab's REAL Number Theory Problem
Ehab's REAL Number Theory Problem 前置知识 质数 分解质因数 无向无权图最小环<讲> Ehab's REAL Number Theory Problem/ ...
- 微信小程序自动化,记录趟过的坑!
项目思想:关键字+数据驱动混合测试 基于Android-微信小程序自动化的关键是:webview的切换 对于微信App来说如何从NATIVE切换到webview的过程 测试版本信息 1.微信版本:7. ...
- [水题日常]Luogu1113 杂务
这几天又在颓. 我的blog难度目前还比较低,主要面向像我这样子的新手(当然内容也会尽量讲得具体清楚一些)x 如果有错误还请指出~ 写完随笔之后才去翻了一下这题题解之后才注意到这题是有序的 QAQ完全 ...
- Nebula Graph 在微众银行数据治理业务的实践
本文为微众银行大数据平台:周可在 nMeetup 深圳场的演讲这里文字稿,演讲视频参见:B站 自我介绍下,我是微众银行大数据平台的工程师:周可,今天给大家分享一下 Nebula Graph 在微众银行 ...
- Python -- 修改、添加和删除元素
大多数列表将是动态的,这意味着列表创建后,将随着程序的运行增删元素. 修改列表元素 修改列表元素的语法与访问列表元素的语法类似.要修改列表元素,可指定表名和要修改的元素指引,再指定该元素的新值. #代 ...
- (十三)、向shell脚本中传参
一.向脚本中传递位置参数 向脚本中传递参数的数目理论上可以无数多,但是只有前9个能被访问,使用shift可以改变此限制 $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 脚本名字 first ...
- 关于META-INF下的spring.factories文件
spring.factories 文件是springboot提供的一种实例化bean方式 org.springframework.boot.autoconfigure.EnableAutoConfig ...
- 6. 抹平差异,统一类型转换服务ConversionService
目录 ✍前言 版本约定 ✍正文 ConverterRegistry ConversionService ConfigurableConversionService GenericConversionS ...