オブジェクトプールPoolsを使用して、頻繁に作成および破棄されるコードを最適化

2759 ワード

前言
Glideのソースコードを読むと、GlideはオブジェクトプールPoolsを多く使用して、頻繁に作成および破棄する必要があるコードを最適化していることがわかります.
たとえばGlideでは,各ピクチャリクエストタスクにEngineJob,DecodeJobクラスが必要である.毎回これらのクラスを再newする必要がある場合は、適切ではありません.また、大量のピクチャリクエストの場合、これらのクラスを頻繁に作成および破棄すると、メモリがジッタし、パフォーマンスに影響を与える可能性があります.
Glideはオブジェクトプールのメカニズムを使用して、頻繁に作成および破棄する必要があるオブジェクトをオブジェクトプールに保存します.オブジェクトを使用するたびに、オブジェクトプールの空きオブジェクトを取得し、フレームワークのパフォーマンスを向上させるために初期化操作を行います.
コード紹介
1.使用するクラスandroid.support.v4.util.Pool
2.Poolインタフェースクラスacquire():オブジェクトプールからオブジェクトを要求する関数:release()オブジェクトをオブジェクトプールに戻す関数
public static interface Pool {

    public T acquire();
    
    public boolean release(T instance);
}

3.Android公式オブジェクトプールの簡単な実現:SimplePoolも、最も多くの実現原理を使用しています.「怠惰なロード」の思想を使用しています.SimplePoolが初期化されると、N個のTタイプのオブジェクトはオブジェクトプールに格納されません.リリースされたTタイプオブジェクトは、release()が外部から呼び出されるたびにオブジェクトプールに格納されます.先に入れてから取り出すことができます.
public static class SimplePool implements Pool {
    private final Object[] mPool;
    private int mPoolSize;
    
    public SimplePool(int maxPoolSize) {
        if (maxPoolSize <= 0) {
            throw new IllegalArgumentException("The max pool size must be > 0");
        }
        mPool = new Object[maxPoolSize];
    }

    @Override
    @SuppressWarnings("unchecked")
    public T acquire() {
        if (mPoolSize > 0) {
            final int lastPooledIndex = mPoolSize - 1;
            T instance = (T) mPool[lastPooledIndex];
            mPool[lastPooledIndex] = null;
            mPoolSize--;
            return instance;
        }
        return null;
    }

    @Override
    public boolean release(T instance) {
        if (isInPool(instance)) {
            throw new IllegalStateException("Already in the pool!");
        }
        if (mPoolSize < mPool.length) {
            mPool[mPoolSize] = instance;
            mPoolSize++;
            return true;
        }
        return false;
    }

    private boolean isInPool(T instance) {
        for (int i = 0; i < mPoolSize; i++) {
            if (mPool[i] == instance) {
                return true;
            }
        }
        return false;
    }
}

4.SynchronizedPoolの簡単なパッケージは、オブジェクトプールの設計によって取り出されるようになっています.したがって、オブジェクトが挿入されていない場合、acquire()を呼び出し、nullを返すので、オブジェクトプールを次のようにカプセル化して使用することができます.
public class MyPooledClass {
  private static final SynchronizedPool sPool =
          new SynchronizedPool(10);

  public static MyPooledClass obtain() {
      MyPooledClass instance = sPool.acquire();
      return (instance != null) ? instance : new MyPooledClass();
  }

  public void recycle() {
      sPool.release(this);
  }
}