您现在的位置是:网站首页> 编程资料编程资料
.net core中高效的动态内存管理方案_实用技巧_
2023-05-24
314人已围观
简介 .net core中高效的动态内存管理方案_实用技巧_
.net core在新增的System.Buffers中引入了一大堆高效内存管理的类,如span和memory、内存池。本文今天这里介绍一个高效动态内存访问方案。
ReadOnlySequenceSegment
在我们读取数据的过程,很多时候会出现如下场景:
不知道数据实际大小
一次性申请大量内存开销太大
此时我们往往会使用动态内存的方案,通过链表的方式串联起来,从而形成逻辑意义上的数据流。如下图所示:

ReadOnlySequenceSegment
Memory:指向所包含的内存
Next:指向下一个节点
RunningIndex:标志当前节点在整个流的位置
其中Memory和Next还比较容易理解,典型的链表结构。主要难理解的是RunningIndex,他表示该节点在数据流中的Memory起始索引。
一般的来讲,某节点的RunningIndex为其上一个节点的RunningIndex + Memory.Length。加上RunningIndex估计主要是为了快速索引的。
例如:对于如下3快内存 100byte, 200byte, 300byte组成的链表,其RunningIndex分别是0, 100, 200。
另外,在实际的使用过程中,往往是不停的释放链表头部的节点,并且在尾部添加新节点。 RunningIndex表示的索引一般是逻辑意义上的索引,在释放头节点时,一般不用更新其子节点以及后续节点的RunningIndex。
ReadOnlySequence
ReadOnlySequenceSegment
为了解决这个问题,.net core中推出了一个视图类ReadOnlySequence

ReadOnlySequence
Start: 起始SequenceSegment以及起始索引
End: 结尾SequenceSegment以及结尾索引
可以通过foreach遍历各节点的Memory
var seq = new ReadOnlySequence(); foreach (ReadOnlyMemory memory in seq) { }
ReadOnlySequence的主要优势在于,它可以看成一段逻辑意义上的连续内存,常用的函数有:
Slice:对视图数据切片
PositionOf:查询元素的缩影
ToArray:转换成数组
其中的ToArray涉及到大量的数据拷贝,需要谨慎使用。
另外.net core 3.0中还内置了一个SequenceReader,用起来是十分方便的:
private static ReadOnlySpanCRLF => new byte[] { (byte)'\r', (byte)'\n' }; public static void ReadLines(ReadOnlySequence sequence) { SequenceReader reader = new SequenceReader (sequence); while (!reader.End) { if (!reader.TryReadToAny(out ReadOnlySpan 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,发现并不是那么容易,因为:
ReadOnlySequence依赖于ReadOnlySequenceSegment
ReadOnlySequenceSegment是抽象类,需要自己继承
也就是说我们需要自己实现ReadOnlySequenceSegment
如果我们要自己实现ReadOnlySequence,一般需要如下几个步骤:
继承ReadOnlySequenceSegment类,实现自己的SequenceSegment
在申请内存过程中,创建SequenceSegment,并将其挂成链表
使用数据时,在该链表中创建ReadOnlySequence
当SequenceSegment节点的内存使用完成的时候,从链表中接触该节点,并释放内存。
简单来说就是如下几种操作:
数据读取: 创建SequenceSegment
数据使用: 在SequenceSegment链表上创建ReadOnlySequence
使用完成: 释放SequenceSegment
如果要更进一步优化,在SequenceSegment中的内存申请和释放可以使用内存池。
到此这篇关于.net core动态内存管理方案的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。
相关内容
- .net加载失败的程序集实现重新加载_实用技巧_
- 使用chrome控制台作为.Net的日志查看器_实用技巧_
- .net新兴日志框架Serilog简介_实用技巧_
- .net core中的System.Buffers命名空间_基础应用_
- .net中的Span<T>类和Memory<T>类介绍_基础应用_
- Rx.NET库中IDisposable对象的用法_实用技巧_
- .net中的DI框架AutoFac简单介绍_实用技巧_
- Asp.net core利用dynamic简化数据库访问_实用技巧_
- Asp.net core实现PushStream视频流推送_实用技巧_
- 在Asp.net core中实现websocket通信_实用技巧_
