NLog源码解读——StringBuilderPool

刚刚骚情的跑了下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);
                }
            }
        }
    }
发布了112 篇原创文章 · 获赞 16 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/webmote/article/details/90055523
今日推荐