刚刚骚情的跑了下NLog测试,,,,,一篇文章就那么Crash了~~~
好吧,这次简化下,直接进入正题,有关GC的东东参考网上大部分文章吧。
源码分析
// StringBuilder 的建立也会耗费大量的资源,因此共用他们,使用这个类来管理池子
//需要了从这里获取一个,用完自动释放 ItemHolder 即可释放会池子
// 例如 using (var itemHolder = pool.Acquire()){}
internal class StringBuilderPool
{
private StringBuilder _fastPool;
private readonly StringBuilder[] _slowPool;
private readonly int _maxBuilderCapacity;
/// <summary>
/// Constructor
/// </summary>
/// <param name="poolCapacity">Max number of items</param>
/// <param name="initialBuilderCapacity">Initial StringBuilder Size</param>
/// <param name="maxBuilderCapacity">Max StringBuilder Size</param>
public StringBuilderPool(int poolCapacity, int initialBuilderCapacity = 1024, int maxBuilderCapacity = 512 * 1024)
{
//一个快速池子,一直保持
_fastPool = new StringBuilder(10 * initialBuilderCapacity);
// 一个慢速池子,如果快速池子被占用,则从慢速池子取一个
_slowPool = new StringBuilder[poolCapacity];
for (int i = 0; i < _slowPool.Length; ++i)
{
_slowPool[i] = new StringBuilder(initialBuilderCapacity);
}
_maxBuilderCapacity = maxBuilderCapacity;
}
/// <summary>
/// Takes StringBuilder from pool
/// </summary>
/// <returns>Allow return to pool</returns>
public ItemHolder Acquire()
{
//1.come on baby,先尝试分配快速池子
StringBuilder item = _fastPool;
//2.如果你幸运的拿到快速池子,则尽快把快速池子置空,不要让别人抢到了,否则,你就必须进慢速池子取了
if (item == null || item != Interlocked.CompareExchange(ref _fastPool, null, item))
{
//3.你好,兄弟,你已经进入慢车道,来,一个个给你试试能用不
for (int i = 0; i < _slowPool.Length; i++)
{
item = _slowPool[i];
if (item != null && item == Interlocked.CompareExchange(ref _slowPool[i], null, item))
{
//4.啊哈,发现一个慢速的,来,给你,别嫌弃
return new ItemHolder(item, this, i);
}
}
//这么倒霉,一个都没有,算了,再给你分配一个新的吧,记住,你的编号~~~咦, 第0个吧~~~
return new ItemHolder(new StringBuilder(), null, 0);
}
else
{
//你是幸运之星,快速跑~~~~
return new ItemHolder(item, this, -1);
}
}
/// <summary>
/// Releases StringBuilder back to pool at its right place
/// </summary>
private void Release(StringBuilder stringBuilder, int poolIndex)
{
//来,兄弟,好借好还,再借不难
//什么,这么大,我记得借你时没这么大啊,让我再检查检查
if (stringBuilder.Length > _maxBuilderCapacity)
{
//我靠,你是快车道的,那就给你10倍大小如何,这都超了,那对不起,减半了~~
// Avoid high memory usage by not keeping huge StringBuilders alive (Except one StringBuilder)
int maxBuilderCapacity = poolIndex == -1 ? _maxBuilderCapacity * 10 : _maxBuilderCapacity;
if (stringBuilder.Length > maxBuilderCapacity)
{
stringBuilder = new StringBuilder(maxBuilderCapacity / 2);
}
}
stringBuilder.Length = 0;
//好,各就各位...
if (poolIndex == -1)
{
_fastPool = stringBuilder;
}
else
{
_slowPool[poolIndex] = stringBuilder;
}
}
/// <summary>
/// Keeps track of acquired pool item
/// </summary>
public struct ItemHolder : IDisposable
{
public readonly StringBuilder Item;
readonly StringBuilderPool _owner;
readonly int _poolIndex;
public ItemHolder(StringBuilder stringBuilder, StringBuilderPool owner, int poolIndex)
{
Item = stringBuilder;
_owner = owner;
_poolIndex = poolIndex;
}
/// <summary>
/// Releases pool item back into pool
/// </summary>
public void Dispose()
{
if (_owner != null)
{
_owner.Release(Item, _poolIndex);
}
}
}
}