dotnet高性能buffer

时间: 2020-12-22阅读: 319标签: 性能

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。优点是内存分配少,缺点是租赁比直接创建小的缓冲区还要慢。

Copy
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性能好,缺点是内存分配高。

Copy
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对象。

Copy
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。

Copy
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里大量应用。

原文:https://www.cnblogs.com/kewei/p/14285873.html

站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: http://www.fly63.com/article/detial/10107

前端性能的本质是什么?

性能一直以来是前端开发中非常重要的话题。随着前端能做的事情越来越多,浏览器能力被无限放大和利用:从 web 游戏到复杂单页面应用,从 NodeJS 服务到 web VR/AR 和数据可视化,前端工程师总是在突破极限

10个快速优化Web性能的手段

优化网站的性能需要花费大量的时间,并且如果要根据自己的需求进行优化则花费的时间可能更多。在本文中,我将向你展示 10 个快速优化 Web 性能的手段,能在 5 分钟内用于你自己的网站

优化 web 应用程序性能方案总结

在开发 web 应用程序时候,性能都是必不可少的话题。而大部分的前端优化机制都已经被集成到前端打包工具 webpack 中去了,当然,事实上仍旧会有一些有趣的机制可以帮助 web 应用进行性能提升

前端性能优化_css加载会造成哪些阻塞现象?

css的加载是不会阻塞DOM的解析,但是会阻塞DOM的渲染,会阻塞link后面js语句的执行。这是由于浏览器为了防止html页面的重复渲染而降低性能,所以浏览器只会在加载的时候去解析dom树,然后等在css加载完成之后才进行dom的渲染以及执行后面的js语句。

编写高性能的JavaScript

随着计算机硬件的不断升级,开发者越发觉得Javascript性能优化的好不好对网页的执行效率影响不明显,所以一些性能方面的知识被很多开发者忽视

PHP性能优化总结

在循环中判断时,数值判断使用恒等要比等于高效。在数组中,数组下标是字母时一定要加上单引号或双引号。因为$row[‘id‘]的效率是$row[id]的7倍。尽量不要在for循环中使用函数

React性能优化整理

通过判断减少数据变化触发的重新渲染, 以及之后的 DOM diff;函数式语言当中, 语言设计允许两个对象一样, 举例 Clojure:;每个函数体当中生成的对象都会有新的引用, useMemo 可以保留一致的引用.

web前端性能优化指南

性能优化一直以来都是前端工程领域中的一个重要部分。很多资料表明,网站应用的性能优化对于提高用户留存、转化率等都有积极影响。可以理解为,提升你的网站性能,就是提升你的业务数据(甚至是业务收入)

JavaScript最佳实践:性能

该函数可能看上去完全正常,但是它包含了三个对于全局document对象的引用。如果在页面上有多个图片,那么for循环中的document引用就会被执行多次甚至上百次,每次都会要进行作用域链查找

PHP性能优化

性能是网站运行是否良好的关键因素, 网站的性能与效率影响着公司的运营成本及长远发展,编写出高质高效的代码是我们每个开发人员必备的素质,也是我们良好的职业素养。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!