ObjectPoolオブジェクトASP.NETコアリユース(B)

序文

前の記事では、知識ObjectPoolの理論を紹介し、Microsoft.Extensions.ObjectPoolが達成されたかを教えています。

画像

コアコンポーネント

ObjectPool

ObjectPoolは、一般的な抽象インタフェースで、彼の抽象二つの方法が取得し、リターン

  • オブジェクトは、オブジェクトを作成することはできませんし、それを返した場合、オブジェクトへの利用可能なプールから取得するためのメソッドを取得します。
  • 復帰方法は、ユーザーオブジェクトプールにオブジェクトを返します。

    /// <summary>
    /// A pool of objects.
    /// </summary>
    /// <typeparam name="T">The type of objects to pool.</typeparam>
    public abstract class ObjectPool<T> where T : class
    {
        /// <summary>
        /// Gets an object from the pool if one is available, otherwise creates one.
        /// </summary>
        /// <returns>A <typeparamref name="T"/>.</returns>
        public abstract T Get();

        /// <summary>
        /// Return an object to the pool.
        /// </summary>
        /// <param name="obj">The object to add to the pool.</param>
        public abstract void Return(T obj);
    }

オブジェクトプールプロバイダ

ObjectPoolProviderが、彼は一般的な方法の一般的な抽象メソッドを構築し、作成します抽象インタフェースで、彼はデフォルトのポリシーに基づいています。


    /// <summary>
    /// A provider of <see cref="ObjectPool{T}"/> instances.
    /// </summary>
    public abstract class ObjectPoolProvider
    {
        /// <summary>
        /// Creates an <see cref="ObjectPool"/>.
        /// </summary>
        /// <typeparam name="T">The type to create a pool for.</typeparam>
        public ObjectPool<T> Create<T>() where T : class, new()
        {
            return Create<T>(new DefaultPooledObjectPolicy<T>());
        }

        /// <summary>
        /// Creates an <see cref="ObjectPool"/> with the given <see cref="IPooledObjectPolicy{T}"/>.
        /// </summary>
        /// <typeparam name="T">The type to create a pool for.</typeparam>
        public abstract ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy) where T : class;
    }
    

IPooledObjectPolicy

IPooledObjectPolicyは、ポリシー管理、オブジェクトプールを提供し、一般的なインタフェースで、このクラスは、2つの方法が定義されて作成してリターンを達成するための戦略を提供するために、

  • 作成は、関連するクラスのインスタンスを作成するために使用されます
  • リセット状態を含む、完全に使用するプールに背中を、置かれている、そしてオブジェクトがプールに戻すことができるかどうかを主題に戻ります

    /// <summary>
    /// Represents a policy for managing pooled objects.
    /// </summary>
    /// <typeparam name="T">The type of object which is being pooled.</typeparam>
    public interface IPooledObjectPolicy<T>
    {
        /// <summary>
        /// Create a <typeparamref name="T"/>.
        /// </summary>
        /// <returns>The <typeparamref name="T"/> which was created.</returns>
        T Create();

        /// <summary>
        /// Runs some processing when an object was returned to the pool. Can be used to reset the state of an object and indicate if the object should be returned to the pool.
        /// </summary>
        /// <param name="obj">The object to return to the pool.</param>
        /// <returns><code>true</code> if the object should be returned to the pool. <code>false</code> if it's not possible/desirable for the pool to keep the object.</returns>
        bool Return(T obj);
    }

PooledObjectPolicyは、一般的な抽象クラスで、実装IPooledObjectPolicy、2つの抽象メソッドの外側を提供します


    public abstract class PooledObjectPolicy<T> : IPooledObjectPolicy<T>
    {
        public abstract T Create();

        public abstract bool Return(T obj);
    }

実装メカニズム

DefaultObjectPool

DefaultObjectPoolは Interlocked.CompareExchange(REF _firstItem、ヌル、ObjectPoolを実現する 、項目) 次に、それ以外の場合は動作しない、同じヌルで_firstItemを置き換え、すべての以前に保存された交換するか、それが返さを交換しないかどうか、_firstItem比較値と項目の値_firstItemの値。

連動操作原子は、複数のスレッドで共有変数として提供されてもよいです。

  • Interlocked.Increment:インクリメント指定された変数の値を格納するアトミック動作の形で結果。
  • Interlocked.Decrementは、アトミックオペレーションの形で結果を与えた変数及び格納をデクリメント。
  • Interlocked.Addアトミック操作、両方の二つの整数の加算と最初の整数を交換し
        public override T Get()
        {
            var item = _firstItem;
            if (item == null || Interlocked.CompareExchange(ref _firstItem, null, item) != item)
            {
                var items = _items;
                for (var i = 0; i < items.Length; i++)
                {
                    item = items[i].Element;
                    if (item != null && Interlocked.CompareExchange(ref items[i].Element, null, item) == item)
                    {
                        return item;
                    }
                }

                item = Create();
            }

            return item;
        }

        public override void Return(T obj)
        {
            if (_isDefaultPolicy || (_fastPolicy?.Return(obj) ?? _policy.Return(obj)))
            {
                if (_firstItem != null || Interlocked.CompareExchange(ref _firstItem, obj, null) != null)
                {
                    var items = _items;
                    for (var i = 0; i < items.Length && Interlocked.CompareExchange(ref items[i].Element, obj, null) != null; ++i)
                    {
                    }
                }
            }
        }

DefaultObjectPoolProvider

DefaultObjectPoolProvider、Crearte ObjectPoolProvider方法で書き換える
だけ使用することができるオブジェクトのデフォルトの最大数(2回CPUプロセッサ)デフォルトEnvironment.ProcessorCount * 2を設定します


    /// <summary>
    /// The default <see cref="ObjectPoolProvider"/>.
    /// </summary>
    public class DefaultObjectPoolProvider : ObjectPoolProvider
    {
        /// <summary>
        /// The maximum number of objects to retain in the pool.
        /// </summary>
        public int MaximumRetained { get; set; } = Environment.ProcessorCount * 2;

        /// <inheritdoc/>
        public override ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy)
        {
            if (policy == null)
            {
                throw new ArgumentNullException(nameof(policy));
            }

            if (typeof(IDisposable).IsAssignableFrom(typeof(T)))
            {
                return new DisposableObjectPool<T>(policy, MaximumRetained);
            }

            return new DefaultObjectPool<T>(policy, MaximumRetained);
        }
    }

DisposableObjectPool

DisposableObjectPoolは DefaultObjectPoolを継承し、IDisposableをオブジェクトが手動で回復するために使用され、実現しました


      public void Dispose()
        {
            _isDisposed = true;

            DisposeItem(_firstItem);
            _firstItem = null;

            ObjectWrapper[] items = _items;
            for (var i = 0; i < items.Length; i++)
            {
                DisposeItem(items[i].Element);
                items[i].Element = null;
            }
        }

        private void DisposeItem(T item)
        {
            if (item is IDisposable disposable)
            {
                disposable.Dispose();
            }
        }

LeakTrackingObjectPool

LeakTrackingObjectPool弱い彼ConditionalWeakTable辞書の参照を定義しObjectPool、およびすべてのすべてのキー値ConditionalWeakTable <処理鍵、TValue>を達成弱参照はであり、かつそのキーまたはキーと値に回収される回収され、自動的に収集から消えました。あなたがフィールドまたはプロパティのいくつかのタイプを添付するためにそれを使用するときに、この手段は、メモリリークの問題を心配するものではありません


    public class LeakTrackingObjectPool<T> : ObjectPool<T> where T : class
    {
        private readonly ConditionalWeakTable<T, Tracker> _trackers = new ConditionalWeakTable<T, Tracker>();
        private readonly ObjectPool<T> _inner;

        public LeakTrackingObjectPool(ObjectPool<T> inner)
        {
            if (inner == null)
            {
                throw new ArgumentNullException(nameof(inner));
            }

            _inner = inner;
        }

        public override T Get()
        {
            var value = _inner.Get();
            _trackers.Add(value, new Tracker());
            return value;
        }

        public override void Return(T obj)
        {
            Tracker tracker;
            if (_trackers.TryGetValue(obj, out tracker))
            {
                _trackers.Remove(obj);
                tracker.Dispose();
            }

            _inner.Return(obj);
        }

        private class Tracker : IDisposable
        {
            private readonly string _stack;
            private bool _disposed;

            public Tracker()
            {
                _stack = Environment.StackTrace;
            }

            public void Dispose()
            {
                _disposed = true;
                GC.SuppressFinalize(this);
            }

            ~Tracker()
            {
                if (!_disposed && !Environment.HasShutdownStarted)
                {
                    Debug.Fail($"{typeof(T).Name} was leaked. Created at: {Environment.NewLine}{_stack}");
                }
            }
        }
    }

参照

https://blog.walterlv.com/post/conditional-weak-table.html

https://www.cnblogs.com/edison0621/p/11747912.html

おすすめ

転載: www.cnblogs.com/yyfh/p/11980645.html