.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,用起来是十分方便的:

如何使用

用过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中的内存申请和释放可以使用内存池。

原文地址:https://www.cnblogs.com/TianFang/p/10084049.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

.net core中的高效动态内存管理方案相关推荐

  1. FreeRTOS 之五 动态内存管理(heap_1.c)详解

    写在前面   写这篇文章时,网上已经有了铺天盖地的文章来介绍 FreeRTOS 的动态内存.之所以还去写这篇博文,主要还是记录自己的学习过程.结合源代码一步一步分析一下FreeRTOS究竟是怎么实现的 ...

  2. 一个基于链表的内存管理方案

    在Open×××中,一种很不错的内存管理方案是基于链表的,该方案的实现使用了一个gc_arena结构体,该结构体的作用就是将所有的动态分配的内存块收集汇集起来,然后就可以在一个地方统一释放,c语言对动 ...

  3. C++学习笔记-DLL中动态内存管理

    动态内存管理 在dll中malloc的内存,必须在dll中free 注:这是由Windows自己的特点决定! 如果 a 编译成静态库,有下面两种解决方法: 1.b.dll 和 c.dll 使用同一个款 ...

  4. LwIP 之五 详解动态内存管理 内存堆(mem.c/h)

    写在前面   目前网上有很多介绍LwIP内存的文章,但是绝大多数都不够详细,甚至很多介绍都是错误的!无论是代码的说明还是给出的图例,都欠佳!下面就从源代码,到图例详细进行说明.   目前,网络上多数文 ...

  5. C++ 动态内存管理:c/c++的动态内存管理,new/delete,operator new/delete,placement-new, 内存泄漏

    c/c++的动态内存管理 new/delete opeartor new/delete placement-new 内存泄漏 c/c++的动态内存管理 在开始之前首先要了解c和c++的内存分布,我简单 ...

  6. 动态内存管理:malloc和free以及new和delete的联系与区别

    动态内存管理:malloc和free以及new和delete的联系与区别 文章目录 动态内存管理:malloc和free以及new和delete的联系与区别 一. C/C++中程序内存区域划分: 二. ...

  7. 内存区划分;内存分配;堆、栈概念分析;动态内存管理数据结构及程序样例;核心态与用户态...

    一. 在c中分为这几个存储区1.栈 - 由编译器自动分配释放 2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 3.全局区(静态区),全局变量和静态变量的存储是放在一块的,初 ...

  8. 【C进阶】动态内存管理

    ⭐博客主页:️CS semi主页 ⭐欢迎关注:点赞收藏+留言 ⭐系列专栏:C语言进阶 ⭐代码仓库:C Advanced 家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们 ...

  9. 【带你吃透C++】C++动态内存管理

    C++动态内存管理 前言 1. C/C++内存分布 例题理解 2.C语言中动态内存管理方式( malloc/calloc/realloc和free) 3.C++中动态内存管理方式 new和delete ...

最新文章

  1. 热度直逼TensorFlow的深度学习框架,我用它画下女朋友最美的脸
  2. CCNA第十一章学习笔记OSPF简介
  3. Excel中这四个常出错的地方,你一定中过!
  4. golang 修改nginx配置文件_「系统架构」Nginx调优,不可错过的几点
  5. ajax渲染后的点击事件,在ajax调用后渲染“喜欢”按钮
  6. 使用国密浏览器和使用Wireshark进行国密抓包
  7. 饿了么想解决外卖小哥马路杀手的问题,但用无人机?
  8. 讲述MPLS技术及其标准化进展
  9. 一步一步学Ruby(五): Class, Module, Object,Kernel的关系
  10. 数据仓库之元数据管理
  11. windows自带黑体_window自带字体
  12. Teechart图表教程:Teechart的组成
  13. 测试计算机性能的软件比较专业,用什么软件可以测试计算机的整体性能?
  14. [精简]快速认识钢琴键盘
  15. 通过Servlet生成验证码图片
  16. 19南大软院上岸学姐考研经验分享
  17. linux开机dracut界面_linux开机启动步骤详解
  18. MySQL按中文排序
  19. centos7切换图像界面和dos界面
  20. Pytorch里addmm()和addmm_()的用法详解

热门文章

  1. javascript原型链中 this 的指向
  2. POJ 2887 Big String
  3. [Windows]_[0基础]_[使用命令行工具dumpbin分析文件]
  4. 源码免杀处理的技巧与tips
  5. GNU ARM 汇编指令[转载]
  6. 五大原则之----里氏替换原则(LSP)
  7. C#类类型“.NET技术”
  8. .NET6之MiniAPI(四):配置
  9. 如何通过 C# kill 指定进程?
  10. .NET 6新特性试用 | 隐式using指令