<NME> ByteArrayPool.java
<BEF> /*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.volley.toolbox;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

/**
 * ByteArrayPool is a source and repository of <code>byte[]</code> objects. Its purpose is to
 * supply those buffers to consumers who need to use them for a short period of time and then
 * dispose of them. Simply creating and disposing such buffers in the conventional manner can
 * considerable heap churn and garbage collection delays on Android, which lacks good management of
 * short-lived heap objects. It may be advantageous to trade off some memory in the form of a
 * permanently allocated pool of buffers in order to gain heap performance improvements; that is
 * what this class does.
 * <p>
 * A good candidate user for this class is something like an I/O system that uses large temporary
 * <code>byte[]</code> buffers to copy data around. In these use cases, often the consumer wants
 * the buffer to be a certain minimum size to ensure good performance (e.g. when copying data
 * chunks
 * off of a stream), but doesn't mind if the buffer is larger than the minimum. Taking this into
 * account and also to maximize the odds of being able to reuse a recycled buffer, this class is
 * free to return buffers larger than the requested size. The caller needs to be able to gracefully
 * deal with getting buffers any size over the minimum.
 * <p>
 * If there is not a suitably-sized buffer in its recycling pool when a buffer is requested, this
 * class will allocate a new buffer and return it.
 * <p>
 * This class has no special ownership of buffers it creates; the caller is free to take a buffer
 * it receives from this pool, use it permanently, and never return it to the pool; additionally,
 * it is not harmful to return to this pool a buffer that was allocated elsewhere, provided there
 * are no other lingering references to it.
 * <p>
 * This class ensures that the total size of the buffers in its recycling pool never exceeds a
 * certain byte limit. When a buffer is returned that would cause the pool to exceed the limit,
 * least-recently-used buffers are disposed.
 */

// 这是一个 byte[] 缓存池，用于 byte[] 的回收再利用，减少内存分配和回收。
public class ByteArrayPool {

    /** The buffer pool, arranged both by last use and by buffer size */
    // 采用 LRU 的机制，最少使用的放在 index=0，最近使用的 放在 index=size()-1
    private List<byte[]> mBuffersByLastUse = new LinkedList<byte[]>();
    // 缓存 byte[] 缓存 List，采用根据 byte[].length 由小到大的方式排序
    private List<byte[]> mBuffersBySize = new ArrayList<byte[]>(64);

    /** The total size of the buffers in the pool */
    // 计算当前缓存池内的所有 byte[] 总长度之和
    private int mCurrentSize = 0;

    /**
     * The maximum aggregate size of the buffers in the pool. Old buffers are discarded to stay
     * under this limit.
     */
    // 缓存池内 byte[] 总长度之和的限制长度，经常拿来与 mCurrentSize 比较
    private final int mSizeLimit;

    /** Compares buffers by size */
    /*
     * 用于比较 byte[].length 的 Comparator
     * lhs.length - rhs.length = 0 ：说明 length 相等
     * lhs.length - rhs.length > 0 ：说明 lhs.length（前者）大
     * lhs.length - rhs.length < 0 ：说明 rhs.length（后者）大
     * 主要用于  Collections.binarySearch 二分查找时，进行的内部排序。
     */
    protected static final Comparator<byte[]> BUF_COMPARATOR = new Comparator<byte[]>() {
        @Override public int compare(byte[] lhs, byte[] rhs) {
            return lhs.length - rhs.length;
        }
    };


    /**
     * @param sizeLimit the maximum size of the pool, in bytes
     */
    // ByteArrayPool 构造方法，需要一个 总 byte[] 长度限制。
    public ByteArrayPool(int sizeLimit) {
        mSizeLimit = sizeLimit;
    }

    /**
     * Returns a buffer from the pool if one is available in the requested size, or allocates a new
     * one if a pooled one is not available.
     *
     * @param len the minimum size, in bytes, of the requested buffer. The returned buffer may be
     * larger.
     * @return a byte[] buffer is always returned.
     */
    /*
     * 根据 长度需求 len，获取一个 length=len 的 byte[] 缓存
     * 如果没有这样“规格”的 byte[]，就 new 一个返回
     */
    public synchronized byte[] getBuf(int len) {
        // 开始遍历 byte[] 缓存数组
        for (int i = 0; i < mBuffersBySize.size(); i++) {
            // 拿到每一个 byte[] 缓存
            byte[] buf = mBuffersBySize.get(i);
            // 如果长度符合了，进行取出 byte[] 缓存前的操作
            if (buf.length >= len) {
                // 先对 总长度 进行削减
                mCurrentSize -= buf.length;
                // 移除 byte[] 缓存组中的 对应 byte[] 缓存
                mBuffersBySize.remove(i);
                // 移除 byte[] LRU 组中的 对应 byte[] 缓存
                mBuffersByLastUse.remove(buf);
                // 最后，返回这个 byte[] 进行再次利用
                return buf;
            }
        }
        // for 循环走完，没返回的话，就是没有符合长度的 byte[]，只能 new 一个返回了。
        return new byte[len];
    }


    /**
     * Returns a buffer to the pool, throwing away old buffers if the pool would exceed its
     * allotted
     * size.
     *
     * @param buf the buffer to return to the pool.
     */
    // 将一个 byte[] 放入缓存池中
    public synchronized void returnBuf(byte[] buf) {
        // 如果 byte[] 为null 或者 byte[] 的长度超过了整个缓存池的总长限制
        if (buf == null || buf.length > mSizeLimit) {
            return;
        }
        // 放入 byte[] LRU 组中的末尾，对应了：最少使用的放在 index=0，最近使用的 放在 index=size()-1
        mBuffersByLastUse.add(buf);
        // 对 缓存组 mBuffersBySize 进行从小到大的排序后，二分查找此次缓存的 byte[] 所应该在的位置
        int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR);
        if (pos < 0) {
            pos = -pos - 1;
        }
        // 在对应位置插入此次缓存的 byte[]
        mBuffersBySize.add(pos, buf);
        // 总长度加上此次 byte[].length
        mCurrentSize += buf.length;
        // 由于加了数据，需要判断是否溢出，并可能进行溢出处理
        trim();
    }


    /**
     * Removes buffers from the pool until it is under its size limit.
     */
    private synchronized void trim() {
        // 如果数据溢出了
        while (mCurrentSize > mSizeLimit) {
            // 从 LRU 组内找出一个最近很少使用的 byte[]，这里也对应了：最少使用的放在 index=0，最近使用的 放在 index=size()-1
            byte[] buf = mBuffersByLastUse.remove(0);
            // 接着拿到从 LRU 组内删除的 byte[]，去缓存组内继续移除该 byte[]
            mBuffersBySize.remove(buf);
            // 总长度减去此次删除的 byte[].length
            mCurrentSize -= buf.length;
        }
    }
}

<MSG> fix ByteArrayPool comments in volley module

<DFF> @@ -53,7 +53,10 @@ import java.util.List;
  * least-recently-used buffers are disposed.
  */
 
-// 这是一个 byte[] 缓存池，用于 byte[] 的回收再利用，减少内存分配和回收。
+/*
+ * 这是一个 byte[] 缓存池
+ * 用于 byte[] 的回收再利用，减少内存分配和回收。
+ */
 public class ByteArrayPool {
 
     /** The buffer pool, arranged both by last use and by buffer size */
@@ -96,6 +99,7 @@ public class ByteArrayPool {
         mSizeLimit = sizeLimit;
     }
 
+
     /**
      * Returns a buffer from the pool if one is available in the requested size, or allocates a new
      * one if a pooled one is not available.

{'addition_count': 5, 'commit_subject': 'fix ByteArrayPool comments in volley module', 'deletion_count': 1, 'file_extension': '.java', 'lang': 'java', 'license': 'apache-2.0', 'repo_name': 'CaMnter/AndroidLife'}