MemoryOwner和SpanOwner都可以理解为是对ArrayPool<>的一个包装,无非一个是在堆栈上,一个是在托管堆上。既然做了包装,那肯定随之而来就是改进和优化。

MemoryOwner<>

MemoryOwner<>解决的问题

1.通过ArrayPool的Api MemoryPool.Shared.Rent(size) 获得的IMemoryPool实例的缓冲区会大于我们指定的大小,一般是2的n次方,所以需要我们去切片去获取真正有意义的段数据。但是MemoryOwner<>会存储我们请求的大小,并且在其属性中,如span,自动为我们切片成我们请求的大小,从而免除了切片的操作。

2.IMemoryPool只有Memory属性,我们需要通过Memory再去获取span,但是MemoryOwner<>本身就有span属性供我们调用

3.ArrayPool返回我们租用的缓冲空间的时候默认不会清空,除非设置clearArray,MemoryOwner<>在Allocate的时候就可以设置AllocationMode从而决定在返还缓冲区的时候是否清空其中数据。

但是清空数据将会带来小小的性能消耗,就是我们需要给每一位填上默认值,即填充0

4.MemoryOwner<>最大的优点,就是会重复使用缓冲池中的某个相同的数组,从而最大程度的避免分配。

如下是我们使用原始数组来存储从文件读取到的数据:

using Stream stream = File.OpenRead(path);
byte[] buffer = new byte[(int)stream.Length];
stream.Read(buffer, 0, buffer.Length);
return buffer;

如果我们读取的是一个大文件,则会在内存中分配一个大内存空间,这会在使用完之后给GC很大的压力。

我们使用ArrayPool对代码做一个优化,目的在于从缓冲池中租用一段空间,以避免空间的分配。

using Stream stream = File.OpenRead(path);
byte[] buffer = ArrayPool<byte>.Shared.Rent((int)stream.Length);
stream.Read(buffer, 0, (int)stream.Length);
//切片数组
return buffer[0..((int)stream.Length - 1)];

上述代码有一个很明显的问题,就是最终我们对数组做了切片,所以还是将旧的缓冲区的数据拷贝到了一个新的数组,并且还存在了分配空间的行为。问题的根源就是ArrayPool租用到的大小实际会大于我们的实际请求。

并且我们返回了数组,那么我们还需要再去跟踪这个数组的使用的生命周期,并且需要再合适的时机去调用ArrayPool<>.Shared.Return(buffer)返还到缓冲池中。

为了解决上述问题,我们再使用MemoryOwner<>去重构代码

using Stream stream = File.OpenRead(path);
MemoryOwner<byte> buffer = MemoryOwner<byte>.Allocate((int)stream.Length);
stream.Read(buffer.Span);
return buffer;

MemoryOwner<>.Allocate(size)返回的IMemoryOwner<> 实例将负责释放基础缓冲区

并且MemoryOwner中的所有属性遵循我们请求的实际大小,从而无需再做切片处理,比如Span属性。

SpanOwner<>

SpanOwner<>是从共享内存池租用再堆栈中的缓冲区的类型,功能和API与MemoryOwner<>类似。

和MemoryOwner<>的区别就是它在堆栈上以及它没有实现IMemoryOwner<>这个接口所以没有Memory<>属性。

代码示例:

SpanOwner<int> buffer = SpanOwner<int>.Allocate(length);
Span<int> span = buffer.Span;

总结

1.SpanOwner和MemoryOwner常被用作缓冲区,存储临时数据

2.可以使用using对SpanOwner和MemoryOwner进行生命周期的控制,对于MemoryOwner来说,如果不方便控制,GC最后也会将其返还到缓冲池中。

3.SpanOwner和MemoryOwner可以理解为是对ArrayPool的包装。

本文参考文档:https://learn.microsoft.com/zh-cn/dotnet/communitytoolkit/high-performance/memoryowner

如有问题,多谢指教!

.net开发者应掌握的利器CommunityToolkit.HighPerformance——MemoryOwner与SpanOwner的更多相关文章

  1. PHP开发者应了解的24个库

    @PHP开发者应了解的24个库 本文由 伯乐在线 - 贾朝藤 翻译.未经许可,禁止转载!英文出处:tutorialzine.欢迎加入翻译组. 作为一个PHP开发者,现在是一个令人激动的时刻.每天有许许 ...

  2. [转贴]PHP 开发者应了解的 24 个库

    作为一个PHP开发者,现在是一个令人激动的时刻.每天有许许多多有用的库分发出来,在Github上很容易发现和使用这些库.下面是我曾经遇到过最酷的24个库.你最喜欢的库没有在这个列表里面?那就在评论中分 ...

  3. 转:PHP开发者应了解的24个库

    原文来自于:http://blog.jobbole.com/54201/ 作为一个PHP开发者,现在是一个令人激动的时刻.每天有许许多多有用的库分发出来,在Github上很容易发现和使用这些库.下面是 ...

  4. Web开发者应知的URL编码知识

    原文出处:http://blog.jobbole.com/42246/ 本文首先阐述了人们关于统一资源定位符(URL)编码的普遍的误读,其后通过阐明HTTP场景下的URL encoding 来引出我们 ...

  5. Web开发者应知的URL编码知识(转)

    原文出处: lunatech   译文出处:oschina - 桔子, lwei, 史涛, Khiyuan, super0555, LinuxQueen, 抛出异常的爱 本文首先阐述了人们关于统一资源 ...

  6. Web开发者应掌握的12个Firebug技巧

    来源: 廖煜嵘 相信很多从事Web开发工作的开发者都听说和使用过Firebug,但可能大部分人还不知道,其实它是一个在网页设计方面功能相当强大的编辑器,它 可以对HTML.DOM.CSS.HTTP和J ...

  7. Apple Pay强势来袭,开发者应做的事情

    "iOS8.1就已经有这个功能了,只是木有现在这么的火,现在的趋势是要火的节奏,因此很多电商平台B2B,P2P,C2C,X2X都有可能需要这个屌丝的付款功能了,在此简单的研究一下." ...

  8. JavaScript开发者应懂的33个概念

    简介 这个项目是为了帮助开发者掌握 JavaScript 概念而创立的.它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南. 本篇文章是参照 @leonardomso 创立,英文版项 ...

  9. Apple Pay强势来袭,开发者应做的事情(转)

    "iOS8.1就已经有这个功能了,只是木有现在这么的火,现在的趋势是要火的节奏,因此很多电商平台B2B,P2P,C2C,X2X都有可能需要这个屌丝的付款功能了,在此简单的研究一下." ...

  10. web开发者踏入人工智能的利器_Tensorflow.js

    前言 最近公司向员工搜集公司杂志的文章,刚好最近学习了机器学习相关课程.为了赚取购买课程的费用,所以写了如下文章投稿赚取稿费. 如下文章可能涉及一些我所购买课程的内容,所以不便将所有资源进行展示. 当 ...

随机推荐

  1. 声网推出首个完整实时合唱解决方案 即将上线“咪哒”全国线下K歌房

    4月20日,声网Agora宣布对实时合唱技术方案全面升级,帮助国内知名迷你KTV品牌"咪哒"实现国内首个支持多终端.多人合唱.高音质的完整实时合唱解决方案的落地,结束了国内K歌行业 ...

  2. SpringBoot——配置嵌入式 Servlet容器

    更多内容,前往 IT-BLOG 一.如何定制和修改Servlet容器的相关配置 前言:SpringBoot 在Web 环境下,默认使用的是 Tomact 作为嵌入式的 Servlet容器: ​[1]修 ...

  3. Linux RedHat 利用 ISO镜像文件制作本地 yum源

    RedHat 利用ISO镜像文件制作本地yum源 [1]创建iso存放目录和挂载目录 1 [root@desktop ~]# cd /mnt/ 2 [root@desktop mnt]# mkdir ...

  4. 简单部署halo博客

    第一步,购买服务器,安装宝塔linux面板. 第二步,在宝塔linux面板的软件商店安装docker管理器 第三步,配置阿里云镜像加速 修改镜像加速 vim /etc/docker/daemon.js ...

  5. 实现一个CRDT工具库——PSet

    PSet 这段代码实现了一个PSet,即Positive Set,是GSet的扩展.PSet是一个集合,支持添加和删除元素,但是不支持重复元素.PSet的实现是通过两个GSet来实现的,一个GSet存 ...

  6. react组件之非受控组件和高阶组件

    非受控组件 受控组件和非受控组件的区别 ----- value import React, { Component } from 'react' export default class extend ...

  7. python程序,实现以管理员方式运行程序,也就是提升程序权限

    quest UAC elevation from within a Python script? 我希望我的Python脚本能够在Vista上复制文件. 当我从普通的cmd.exe窗口运行它时,不会生 ...

  8. LINUX 下LAMP之yum方法部署环境

    一. 系统组成 系统由前台网站和后台保种服务两部分组成,其中后台保种可以扩展成多台设备,提高保种的资源量以及性能.下面安装以houtaiip代表后台保重服务器ip地址,qiantaiip代表前台网站i ...

  9. 【LeetCode】232.使用栈模拟队列

    使用栈模拟队列 ​ 请你仅使用两个栈实现先入先出队列.队列应当支持一般队列支持的所有操作(push.pop.peek.empty):实现 MyQueue 类: void push(int x) 将元素 ...

  10. golang 必会之 pprof 监控系列(5) —— cpu 占用率 统计原理

    golang pprof 监控系列(5) -- cpu 占用率 统计原理 大家好,我是蓝胖子. 经过前面的几节对pprof的介绍,对pprof统计的原理算是掌握了七八十了,我们对memory,bloc ...