.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等小巧的工具,本博客希望 ...
随机推荐
- OI卷题记录
2021.8.2 LG3386 匈牙利算法 二分图 LG1377 笛卡尔树 题解 2021.8.3 LG2962 \(\text{Meet in middle}\) LG3389 高斯消元 高斯-约旦 ...
- 2010 NOIP提高组题解
机器翻译 用队列模拟题意即可 #include<cstdio> #include<iostream> #include<cstring> using namespa ...
- Python从零开始编写控制程序(一)
Python之从零开始编写控制程序(一) 在此声明:本博客仅供学习参考,任何产生相关违法犯罪行为与本人无关. 另外如果有师傅有好的思路和想法,可以和我一起沟通交流. 最近在一直尝试做Powershel ...
- 毕业设计java实验室预约管理系统SSH机房预约系统javaweb机房实验室排课系统mysql机房管理系统 实验室管理系统 课程设计 代码讲解 调试运行
毕业设计java实验室预约管理系统SSH机房预约系统javaweb机房实验室排课系统mysql机房管理系统 实验室管理系统 课程设计 代码讲解 调试运行 注意:该项目只展示部分功能,如需了解,评论区咨 ...
- Python - typing 模块 —— 类型别名
前言 typing 是在 python 3.5 才有的模块 前置学习 Python 类型提示:https://www.cnblogs.com/poloyy/p/15145380.html 常用类型提示 ...
- STM32—驱动六轴MPU6050输出欧拉角
文章目录 一.MPU6050介绍 1.MPU6050与陀螺仪.加速度计的关系: 2.整体概括 3.引脚说明 4.基本配置及相关寄存器 电源管理寄存器1 陀螺仪配置寄存器 加速度计配置寄存器 FIFO使 ...
- 如何快速方便的生成好看的接口文档(apipost生成文档)
一键生成文档 我们在"2分钟玩转APIPOST"一讲中,简单介绍了如何生成并分享接口文档: 点击分享文档 复制并打开文档地址就可以看到了完整的接口文档. 本节课主要是讲解一些需要注 ...
- Windows Go 开发环境下载、安装并配置
前言 对于我们Windows用户而言,Go提供两种环境安装方式(源码安装除外): 1.MSI安装(MSI文件是Windows Installer的数据包,它实际上是一个数据库,包含安装一种产品所需要的 ...
- NOIP 模拟 7 寿司
题解 题目 这道题考试的时候直接打暴力,结果暴力连样例都过不了,最后放上去一个玄学东西,骗了 \(5pts\). 正解: 此题中我们可以看到原序列是一个环,所以我们要把它拆成一条链,那么我们需要暴力枚 ...
- NOIP 模拟 $14\; \text{影魔}$
题解 \(by\;\;zj\varphi\) 不是原题 一道(对我来说)很需要技巧的题 对于颜色数如何处理 离线,将子树转化为 \(dfs\) 序,但这种做法无法处理深度 我们按照深度加点(可以通过 ...