.NET Core 中的高效动态内存管理方案

2018 年 12 月 12 日 DotNet

(给DotNet加星标,提升.Net技能


转自:天方

cnblogs.com/TianFang/p/10084049.html


.NET Core在新增的System.Buffers中引入了一大堆高效内存管理的类

如span和memory、内存池。


本文今天这里介绍一个高效动态内存访问方案。


ReadOnlySequenceSegment<T>


在我们读取数据的过程,很多时候会出现如下场景:


  1. 不知道数据实际大小


  2. 一次性申请大量内存开销太大


此时我们往往会使用动态内存的方案,通过链表的方式串联起来,从而形成逻辑意义上的数据流。如下图所示:



ReadOnlySequenceSegment<T>就是这样一个表示数据流节点的内存模型,它是一个抽象类,包含如下三个元素:


  • Memory      指向所包含的内存


  • Next            指向下一个节点


  • RunningIndex     标志当前节点在整个流的位置


其中Memory和Next还比较容易理解,典型的链表结构。


主要难理解的是RunningIndex,他表示该节点在数据流中的Memory起始索引。


一般的来讲,某节点的RunningIndex为其上一个节点的RunningIndex + Memory.Length。加上RunningIndex估计主要是为了快速索引的。


例如:对于如下3快内存 100byte, 200byte, 300byte组成的链表,其RunningIndex分别是0, 100, 200。


另外,在实际的使用过程中,往往是不停的释放链表头部的节点,并且在尾部添加新节点。 


RunningIndex表示的索引一般是逻辑意义上的索引,在释放头节点时,一般不用更新其子节点以及后续节点的RunningIndex。


ReadOnlySequence<T>


ReadOnlySequenceSegment<T>虽然能解决我们的动态内存的申请和释放问题,但它往往并不好用,因为很容易出现一段连续的数据被分割在多个节点的情况,在这段不连续的数据里进行查询是非常不便的。


为了解决这个问题,.net core中推出了一个视图类ReadOnlySequence<T>



ReadOnlySequence<T>由两个属性标记:


  • Start: 起始SequenceSegment以及起始索引


  • End: 结尾SequenceSegment以及结尾索引


可以通过foreach遍历各节点的Memory


var seq = new ReadOnlySequence<byte>();
foreach (ReadOnlyMemory<byte> memory in seq)
{
}


ReadOnlySequence的主要优势在于,它可以看成一段逻辑意义上的连续内存,常用的函数有:


  • Slice: 对视图数据切片


  • PositionOf: 查询元素的缩影


  • ToArray: 转换成数组


其中的ToArray涉及到大量的数据拷贝,需要谨慎使用。


另外.net core 3.0中还内置了一个SequenceReader,用起来是十分方便的: 


private static ReadOnlySpan<byte> CRLF => new byte[] { (byte)'\r', (byte)'\n' };
public static void ReadLines(ReadOnlySequence<byte> sequence)
{
   SequenceReader<byte> reader = new SequenceReader<byte>(sequence);
   while (!reader.End)
   {
       if (!reader.TryReadToAny(out ReadOnlySpan<byte> line, CRLF, advancePastDelimiter: false))
       {
           // Couldn't find another delimiter
           // ...
       }
       if (!reader.IsNext(CRLF, advancePast: true))
       {
           // Not a good CR/LF pair
           // ...
       }
       // line is valid, process
       ProcessLine(line);
   }
}


如何使用


用过System.IO.Pipelines的朋友就知道,ReadOnlySequence在该库中是非常好用的。但如果我们想常见一个ReadOnlySequence,发现并不是那么容易,因为:


  1. ReadOnlySequence依赖于ReadOnlySequenceSegment


  2. ReadOnlySequenceSegment是抽象类,需要自己继承


也就是说我们需要自己实现ReadOnlySequenceSegment<T>,然后再将其封装到ReadOnlySequence中,目前.NET Core 中并没有内置实现可能是因为在高效内存管理的方案中并没有什么通用的解决方案吧。


如果我们要自己实现ReadOnlySequence,一般需要如下几个步骤:


  1. 继承ReadOnlySequenceSegment类,实现自己的SequenceSegment


  2. 在申请内存过程中,创建SequenceSegment,并将其挂成链表


  3. 使用数据时,在该链表中创建ReadOnlySequence


  4. 当SequenceSegment节点的内存使用完成的时候,从链表中接触该节点,并释放内存。


简单来说就是如下几种操作:


  • 数据读取: 创建SequenceSegment


  • 数据使用: 在SequenceSegment链表上创建ReadOnlySequence


  • 使用完成: 释放SequenceSegment


如果要更进一步优化,在SequenceSegment中的内存申请和释放可以使用内存池。


推荐阅读

(点击标题可跳转阅读)

初试 C# 8.0

打造自己的.NET Core项目模板

ASP.NET Core 一行代码搞定文件上传


看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

登录查看更多
0

相关内容

.NET 框架(.NET Framework) 是由微软开发,一个致力于敏捷软件开发、快速应用开发、平台无关性和网络透明化的软件开发平台。
专知会员服务
78+阅读 · 2020年6月20日
【实用书】流数据处理,Streaming Data,219页pdf
专知会员服务
76+阅读 · 2020年4月24日
【SIGMOD2020-腾讯】Web规模本体可扩展构建
专知会员服务
29+阅读 · 2020年4月12日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
68+阅读 · 2020年1月17日
【文献综述】边缘计算与深度学习的融合综述论文
专知会员服务
158+阅读 · 2019年12月26日
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
Tensorflow框架是如何支持分布式训练的?
AI100
9+阅读 · 2019年3月26日
【泡泡一分钟】动态环境下的高效长时间建图
泡泡机器人SLAM
6+阅读 · 2019年2月1日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
.NET Core 环境下构建强大且易用的规则引擎
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Do RNN and LSTM have Long Memory?
Arxiv
19+阅读 · 2020年6月10日
Arxiv
10+阅读 · 2020年4月5日
Arxiv
5+阅读 · 2018年4月22日
Arxiv
3+阅读 · 2018年3月29日
VIP会员
相关资讯
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
Tensorflow框架是如何支持分布式训练的?
AI100
9+阅读 · 2019年3月26日
【泡泡一分钟】动态环境下的高效长时间建图
泡泡机器人SLAM
6+阅读 · 2019年2月1日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
.NET Core 环境下构建强大且易用的规则引擎
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Top
微信扫码咨询专知VIP会员