当系统中需要大量的频繁分配释放内存,且对数据处理时间存在较高要求时,可以采用预分配内存,然后自行管理的方式。下面是一种简单的实现方式,只能分配定长数组而且不支持并发访问。
使用数组作为载体,每个数组都为一个内存结构,使用时查找未被使用的内存结构获取其引用。所使用的内存长度全部固定,适用于定长数组的分配。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//TODO:暂不支持并发访问
namespace MemoryManager
{
//内存结构
public struct MemorySturct<T>
{
internal bool isUsed; //表示此结构是否被使用
public int Locate{ get; internal set; } //表示此缓存的数组下标,此值为-1代表分配失败
public T[] buffer; //实际的缓冲内存
}
public class ArraryMemory<T>
{
private static int maxMemoryStructNum = 100; //内存结构的最大数量
private MemorySturct<T>[] _memory;
public ArraryMemory(uint bufferSize,int memoryStructNum=100)
{
if (bufferSize == 0 || memoryStructNum == 0)
throw new ArgumentException();
maxMemoryStructNum = memoryStructNum;
_memory = new MemorySturct<T>[maxMemoryStructNum];
for (int i = 0; i < maxMemoryStructNum; i++)
{
_memory[i].isUsed = false;
_memory[i].Locate = i;
_memory[i].buffer = new T[maxMemoryStructNum];
}
}
public MemorySturct<T> MallocBuffer()
{
for (int i = 0; i < maxMemoryStructNum; i++)
{
if (_memory[i].isUsed == false)
{
_memory[i].isUsed = true;
return _memory[i];
}
}
MemorySturct<T> buffer = new MemorySturct<T>();
buffer.Locate = -1;
return buffer;
}
public void FreeBuffer(MemorySturct<T> buffer)
{
if (buffer.Locate == -1)
throw new ArgumentException();
_memory[buffer.Locate].isUsed = false;
}
public static bool IsCorrect(MemorySturct<T> buffer)
{
return (buffer.Locate == -1) ? false : true;
}
}
}
下面两张图是运行结果。
第一张图是不使用内存管理的方式,运行中分配内存,会出现大量的延时;
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPBplZKhlWwJ1RiZnTzwEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3Pn5GcuEDN0EDN1ETMyIzMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
第二张图是使用了内存管理后的运行结果,除了首次分配出现延迟之外其他情况基本不存在延迟。