再谈高性能Web服务器,MemoryPool的作用

在以往使用c#实现scoket服务器中,通常遇到一个问题就是内存占用高,GC次数频繁,导致处理能力直线下降

其主要原因是在处理socket请求时,大量的申请,复制内存,为了解决这个问题,NET Core 2.1引入了Span<T>,Memory<T>,MemoryPool<T>操作类型

其主要目的是能够像c/c++一样,使用指针去访问,释放内存,提供一种高性能,可复用的内存处理方式

 

在Kestrel 2.1中,就使用了Span<T>,Memory<T>,MemoryPool<T>处理socket请求,这也是Kestrel 2.1性能强大的原因之一

 

MemoryPool是一个抽象类,提供了以下几个方法供使用

public static MemoryPool<T> Shared { get; } //获取全局共享的默认内存池
public abstract int MaxBufferSize { get; } //每次可获取的最大内存大小

public void Dispose(); //释放内存池,申请的内存也一并释放
public abstract IMemoryOwner<T> Rent(int minBufferSize = -1); //申请一个内存块,可以指定最小大小,默认为-1自动分配
protected abstract void Dispose(bool disposing);

 

申请到内存块 IMemoryOwner<T> 后,可以通过该接口获取Memory<T>, Memory<T>其实就是Span<T>的工厂

Span<T>的操作方式以及性能跟Array<T>差不多,它是一种内存视图的表达方式,包含了目标内存的开始位置,内存长度

 

我们操作的Span<T>时,首先将index加上start位置,然后再从对应的Memory<T>的位置获取数据

 

Memory<T>与Span<T>都是struct类型,jit编译后,其对应真实的内存块,其读取也是通过内存指针直接操作,性能上跟c/c++是一样的

Memory<T>在释放后将会return回MemoryPool中,MemoryPool将会重新分配内存块,实现内存的复用

 

所以NET Core 2.1的Memory<T>与Span<T>类型,非常适合开发高性能Web服务器,游戏服务器

posted @ 2018-08-13 06:17  幻影gool  阅读(547)  评论(1编辑  收藏  举报