.Net性能调优-MemoryPool
简单用法
//获取MemoryPool实例,实际返回了一个ArrayMemoryPool<T>
MemoryPool<char> Pool = MemoryPool<char>.Shared;
//加上using
using IMemoryOwner<char> owner = Pool.Rent(1024 * 900);
Memory<char> memory = owner.Memory;
for (int i = 0; i < 1024 * 900; i++)
{
memory.Span[i] = 'x';
}
//从100的下标开始截取10个字符
var sliceArr = memory.Span.Slice(100, 10).ToArray();
ArrayMemoryPool<T>
通过MemoryPool<int>.Shared我们可以获取到一个MemoryPool<T>的示例,该实例的类型为ArrayMemoryPool<T>
ArrayMemoryPool<T>实际上只有一个函数可用,就是Rent(),还有一个Dispose()函数但是里面没有任何代码
Rent()限制了最大租借长度:2147483647u=(1024^3*2-1)=(2G-1bytes),并返回一个IMemoryOwner<T>对象
ArrayMemoryPoolBuffer<T>
ArrayMemoryPool<T>的Rent()实际返回了一个ArrayMemoryPoolBuffer<T>,该类继承了IMemoryOwner<T>
它提供一个Memroy属性来获取一个Memory<T>对象,我们可以借助Memroy<T>来操控我们租用的数组了
ArrayMemoryPool<T>的内部实际还是调用的ArrayPool<T>.Shared 来租用数组
实现代码如下:
public Memory<T> Memory
{
get
{
T[] array = _array;
if (array == null)
{
System.ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();
}
return new Memory<T>(array);
}
}
public ArrayMemoryPoolBuffer(int size)
{
_array = ArrayPool<T>.Shared.Rent(size);
}
public void Dispose()
{
T[] array = _array;
if (array != null)
{
_array = null;
ArrayPool<T>.Shared.Return(array);
}
}
Memory<T>
Memory<T>的构造函数接收一个array<T>,存在私有变量_object中。Memory中对数组的操作最终又依赖于Span<T>
public readonly struct Memory<T> : IEquatable<Memory<T>>
{
private readonly object _object;
private readonly int _index;
private readonly int _length;
public static Memory<T> Empty => default(Memory<T>);
public int Length => _length;
public bool IsEmpty => _length == 0;
public unsafe Span<T> Span=>{ _object...}
public T[] ToArray()
{
return Span.ToArray();
}
}
Slice(start,length)
public Memory<T> Slice(int start)
{
return new Memory<T>(_object, _index + start, _length - start);
}
Memory的Slice函数可以对数组进行截取,该函数仍然返回一个Memory<T>对象,新的对象记录了原始的_object和要切割的index、length,所以该函数不会造成额外的内存消耗
Pin()
该函数的作用是获取数组内存的管理权,不让垃圾回收器回收,自己管理内存,但他怎么自己管理的,暂时木有研究。。。有兴趣的小伙伴可以自行研究。
但是因为我们的数组是从ArrayPool<T>租借的,由ArrayMemoryPool<T>的Dispose函数回收的,所以本文对于Memory的使用方式中并不会用到该函数
所以综上所述,简单的理解就是Memory<T>主要是用来管理Span<T>的
那么Span又是啥呢?为什么Memrory<T>不直接提供操作数组的方式,而是要返回一个Span<T>呢?
啊哈哈,这个就问倒我了
简单地概括其原因就是通过Span<T>来操作数组切割分片赋值等,更快,更节约内存,数据流转无复制。而Span本身过于底层,使用方面有很多的局限性。所以最终改用Memory<T>来控制Span<T>的生命周期,而只给用户提供Span的操作数组的相关函数。
至于它怎么底层了,局限性在哪些方面,想深入研究的话网上有很多相关的优秀文章值得阅读一下。对于Span的学习我现在是适可而止,后面把内存需要学习的相关知识学的差不多的时候再回来研究它吧,欠的债早晚是要还的啊...
使用场景
啊这...,对于MemoryPool,确实没有想到使用场景。因为之前的文章曾经介绍过ArrayPool。而MemoryPool的数组又是依赖ArrayPool创建的,反而相比于ArrayPool他又多了创建IMemoryOwner的消耗。这里推荐一篇文章对二者进行了对比:https://endjin.com/blog/2020/09/arraypool-vs-memorypool-minimizing-allocations-ais-dotnet。
其实我们更需要的是Memory<T>和Span<T>,在System.Memory命名空间下的MemoryExtensions为我们的Array[]提供了扩展方法AsMemory\<T\>(this T[]? array) AsSpan\<T\>(this T[]? array)等等几十种扩展,足够满足你的需要
所以如果不是非得要用MemoryPool的场景还是推荐直接使用ArrayPool吧,当然如果你有必须使用MemoryPool的场景还请在下面留言告诉我一下是什么场景,互相学习一下,嘿嘿
.Net性能调优-MemoryPool的更多相关文章
- [Spark性能调优] 源码补充 : Spark 2.1.X 中 Unified 和 Static MemoryManager
本课主题 Static MemoryManager 的源码鉴赏 Unified MemoryManager 的源码鉴赏 引言 从源码的角度了解 Spark 内存管理是怎么设计的,从而知道应该配置那个参 ...
- web前端性能调优
最近2个月一直在做手机端和电视端开发,开发的过程遇到过各种坑.弄到快元旦了,终于把上线了.2个月干下来满满的的辛苦,没有那么忙了自己准备把前端的性能调优总结以下,以方便以后自己再次使用到的时候得于得心 ...
- [网站性能2]Asp.net平台下网站性能调优的实战方案
文章来源:http://www.cnblogs.com/dingjie08/archive/2009/11/10/1599929.html 前言 最近帮朋友运营的平台进行了性能调优,效果还不错, ...
- Asp.net平台下网站性能调优的实战方案(转)
转载地址:http://www.cnblogs.com/chenkai/archive/2009/11/07/1597795.html 前言 最近帮朋友运营的平台进行了性能调优,效果还不错,所以写出来 ...
- 第0/24周 SQL Server 性能调优培训引言
大家好,这是我在博客园写的第一篇博文,之所以要开这个博客,是我对MS SQL技术学习的一个兴趣记录. 作为计算机专业毕业的人,自己对技术的掌握总是觉得很肤浅,博而不专,到现在我才发现自己的兴趣所在,于 ...
- sqlserver性能调优第一步
相信不少的朋友,无论是做开发.架构的,还是DBA等,都经常听说“调优”这个词.说起“调优”,可能会让很多技术人员心头激情澎湃,也可能会让很多人感觉苦恼,不知道如何入手.当然,也有很多人对此不屑一顾,因 ...
- JavaScript:内存泄露、性能调优
1.在进行JS内存泄露检查之前,先要了解JS的内存管理: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Manageme ...
- hadoop 性能调优与运维
hadoop 性能调优与运维 . 硬件选择 . 操作系统调优与jvm调优 . hadoop运维 硬件选择 1) hadoop运行环境 2) 原则一: 主节点可靠性要好于从节点 原则二:多路多核,高频 ...
- JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解
摘要: JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jstack.jmap.jhat.jstat.hprof等小巧的工具,本博客希望 ...
随机推荐
- time_formatter writeup
攻防世界time_formatter writeup UAF漏洞和命令注入. 前置知识 1.strdup函数 char * __strdup(const char *s) { size_t len = ...
- CSS实现隐藏滚动条并可以滚动内容
方法一: 计算滚动条宽度并隐藏起来,其实我只是把滚动条通过定位把它隐藏了起来,下面给一个简化版的代码: <div class="outer-container"> &l ...
- 【笔记】偏差方差权衡 Bias Variance Trade off
偏差方差权衡 Bias Variance Trade off 什么叫偏差,什么叫方差 根据下图来说 偏差可以看作为左下角的图片,意思就是目标为红点,但是没有一个命中,所有的点都偏离了 方差可以看作为右 ...
- C#10在List, Queue 以及Stack中使用EnsureCapacity方法来提升性能
简介 在今天的文章中,我们将介绍 C# 10 中引入的一项新功能.这是已添加到 List.Queue 和 Stack 集合中的 EnsureCapacity 方法.我们将讨论为什么我们应该使用这个方法 ...
- 题解 v
传送门 考场上只会爆搜--觉得重复状态其实有很多但不知道怎么记忆化,结果-- 对于类似这样n不算太小但只有二三十,而重复状态极多的题其实也是可以跑状压/记搜的,状态可以开map存 然后就是爆搜,就没什 ...
- SSM自学笔记(一)
本文内容 Ioc和DI Spring快速入门 Spring配置文件 Spring IoC和DI注解开发 Spring配置数据源 Spring注解开发 Spring整合Junit IoC 和 DI 1. ...
- WPF LiveChart 图表详解
//参考网址:https://www.cnblogs.com/zh7791/p/12617961.html 本文主要介绍LiveChart.WPF 中的图表的使用方法 类: 数据绑定, 数据显示样式等 ...
- httpClient 下载
private void button2_Click(object sender, EventArgs e) { get(); } private async Task get() { await D ...
- 【springboot】集成swagger
1.简介 本章介绍 SpringBoot2.1.9 集成 Swagger2 生成在线的API接口文档. 2. pom依赖: 通过对比了swagger的几个版本,发现还是2.6.1问题最少 <!- ...
- 【springboot】自动装配原理
摘自:https://mp.weixin.qq.com/s/ZxY_AiJ1m3z1kH6juh2XHw 前言 Spring翻译为中文是"春天",的确,在某段时间内,它给Java开 ...