最近研究了一下.net core 2.1的基础类库,发现它引入了一个system.buffers名字空间,里面提供了一系列比较实用的对象,便简单的管中窥豹浏览一下。
arraypool<t>
arraypool<t>是一个数组类型的对象池,本身arraypoo<t>是一个抽象类,但他有一个默认的实现arraypoo<t>. shared,使用方法如下:
var pool = arraypool<byte>.shared; var buffer = pool.rent(2048); try { //使用buffer } finally { pool.return(buffer); //归还buffer后不要再使用 }
方法比较简单:
- 通过rent从对象池中申请buffer
- 使用完后,通过return将buffer归还至对象池
微软的文档上并没有详细描述默认的arraypoo<t>的对象申请算法。
不过并不复杂,和传统的对象池的维护方式也差不多:
- 系统维持着一个对象池
- 调用rent的时候,首先会到对象池中查看是否有合适的对象(至少要满足最小长度),如果有则直接返回对象池中的对象,并将其从对象池中移除
- 调用return时,将对象放置到对象池,从而可以作为下次rent的候选对象
注:这里只记录了主要相关功能,实际算法比这个复杂。另外,由于没有很详细看实现方式,如要描述不正确的地方欢迎指正
也就是说,return后的对象,很可能被别的地方rent走,因此可能导致读写冲突。(类似于c语言中的野指针,但仍然是安全的,不会造成内存错误)
memorypool<t>
除了arraypool外,system.buffers名字空间下还提供了一个memorypool,它的使用方式和arrapool比较类似,基本示例如下:
var pool = memorypool<byte>.shared; var buffer = pool.rent(2048); try { var memory = buffer.memory; //use memory<byte> } finally { buffer.dispose(); }
整个过程还是非常类似的,不过释放的时候是调用的dispose方法,用起来实际要更加方便点。不过这里申请到的是memory<t>对象,可能有的地方不像byte[]那样适用 。
关于memorypool的实现,我在github上找了一下,还没有看到。不过由于它返回的是memory<t>,理论上来讲应该是有更高的效率。(例如,可以把一个大段的buffer分成多个memory返回,从而减少申请新对象)
binaryprimitives
binaryprimitives位于system.buffers.binary名字空间下,它提供了一系列数字和字节互相转换的函数。
它的主要好处是是提供了常用bigendian类型的数字的支持,在网络编程或者文件解析的方式的时候非常实用,免得造轮子了。
utf8parser、utf8formatter和base64
这三个类位于system.buffers.text下,它主要用于utf8编码和base64编码下的常用类型的读写,如datetime,guid,bool等,并且支持常用的序列化方式。。
到此这篇关于system.buffers命名空间的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持代码网。
发表评论