using Microsoft.Extensions.ObjectPool;
private ArrayPool<int> _arrayPool = System.Buffers.ArrayPool<int>.Create(1024*1024*1024, 5);
private DefaultPooledObjectPolicy<A> _poolPolicy = new DefaultPooledObjectPolicy<A>();
private ObjectPool<A> _pool;
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
while (true)
{
RunObjByPool();
Thread.Sleep(1000);
}
});
}
private void RunObjByPool()
{
ShowLog("RunByPool-Started");
var list = new List<A>();
var rand = new Random();
var bytes = new int[100];
for (var i = 0; i < 100; i++)
{
var item1 = _pool.Get();
item1.ID = i;
var chars = $"hello{i + 1}".ToArray();
item1.StrLen = chars.Length;
Array.Clear(item1.F1, 0, item1.F1.Length);
Array.Copy(chars, item1.F1, chars.Length);
Array.Clear(item1.F2, 0, item1.F2.Length);
for (var j = 0; j < 100; j++)
bytes[j] = i;
Array.Copy(bytes, item1.F2, bytes.Length);
item1.Weight = rand.Next(100);
Debug.WriteLine(item1.ToString());
list.Add(item1);
}
foreach(var item in list)
_pool.Return(item);
ShowLog("RunByPool-Finished");
}
private void RunNewObj()
{
ShowLog("Run-Started");
var rand = new Random();
var list = new List<A>();
var bytes = new int[100];
for (var i = 0; i < 100; i++)
{
var item1 = new A();
item1.ID = i;
var chars = $"hello{i + 1}".ToArray();
item1.StrLen = chars.Length;
Array.Clear(item1.F1, 0, item1.F1.Length);
Array.Copy(chars, item1.F1, chars.Length);
Array.Clear(item1.F2, 0, item1.F2.Length);
for (var j = 0; j < 100; j++)
bytes[j] = i;
Array.Copy(bytes, item1.F2, bytes.Length);
item1.Weight = rand.Next(100);
Debug.WriteLine(item1.ToString());
list.Add(item1);
}
ShowLog(list.Count.ToString());
ShowLog("Run-Finished");
}
private void Form1_Load(object sender, EventArgs e)
{
_pool = new DefaultObjectPool<A>(_poolPolicy, 1000);
}
private void ShowLog(string log)
{
Invoke(new Action(()=>textBox1.AppendText($"{log}\r\n")));
}
private void button2_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
while (true)
{
RunNewObj();
Thread.Sleep(1000);
}
});
}
private void button3_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => {
while (true)
{
RunArrByPool();
Thread.Sleep(1000);
}
});
}
private void RunArrByPool()
{
double res = 0;
for(var i = 1; i < 1000; i++)
{
var arr = _arrayPool.Rent(i * 100);
for (var j = 0; j < arr.Length; j++)
arr[j] = i * j;
res += arr.Average();
_arrayPool.Return(arr);
}
ShowLog($"{res}");
}
private void RunArr()
{
double res = 0;
for (var i = 1; i < 1000; i++)
{
var arr = new int[i * 100];
for (var j = 0; j < arr.Length; j++)
arr[j] = i * j;
res += arr.Average();
}
ShowLog($"{res}");
}
private void button4_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => {
while (true)
{
RunArr();
Thread.Sleep(1000);
}
});
}
private void button5_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => {
while (true)
{
RunArrByPool();
Thread.Sleep(1000);
}
});
}
public class A
{
public int ID { get; set; }
public int StrLen { get; set; }
public char[] F1 { get; set; } = new char[1024*1024];
public int[] F2 { get; set; } = new int[1024 * 1024];
public int Age { get; set; }
public float Weight { get; set; }
public override string ToString()
{
return $"{ID}-{new string(F1, 0, StrLen)}-{F2.Average()}-{Age}-{Weight}\r\n";
}
}
ObjectPool测试结论:DefaultObjectPool的第二个参数设置合理的缓存大小,应用过程中可以确保无GC,内存稳定;如不启用缓存机制,大量new A对象,频繁GC,内存量跳跃。
ArrayPool测试结论:引入ArrayPool后,从其中获取内存,进程无GC,无WorkSet变化;改为数组方式大量GC,内存暴涨。
查看Get、Return方法,里面有无锁安全机制,并使用线程安全容器队列存储,因此多线程下放心使用。