option(ChannelOption.RCVBUF_ALLOCATOR,new AdaptiveRecvByteBufAllocator(DEFAULT_MINIMUM,DEFAULT_INITIAL,DEFAULT_MAXIMUM))或者option(ChannelOption.RCVBUF_ALLOCATOR,new AdaptiveRecvByteBufAllocator())
接下来看源码:
1 public class AdaptiveRecvByteBufAllocator extends DefaultMaxMessagesRecvByteBufAllocator { 2 //接收缓冲区最小长度下限 3 static final int DEFAULT_MINIMUM = 64; 4 //接收缓冲区初始化 5 static final int DEFAULT_INITIAL = 2048; 6 //接收缓冲区最大长度上限 7 static final int DEFAULT_MAXIMUM = 65536; 8 //扩容增长量 9 private static final int INDEX_INCREMENT = 4; 10 //扩容减少量 11 private static final int INDEX_DECREMENT = 1; 12 private static final int[] SIZE_TABLE; 13 /** @deprecated */ 14 @Deprecated 15 public static final AdaptiveRecvByteBufAllocator DEFAULT; 16 private final int minIndex; 17 private final int maxIndex; 18 private final int initial; 19 //入参是一个大小,然后利用二分查找法对该数组进行size的定位,目标是为了找出该size值在数组中的下标位置,主要是为了初始化minIndex、maxIndex这两个参数 20 private static int getSizeTableIndex(int size) { 21 int low = 0; 22 int high = SIZE_TABLE.length - 1; 23 24 while(high >= low) { 25 if (high == low) { 26 return high; 27 } 28 29 int mid = low + high >>> 1; 30 int a = SIZE_TABLE[mid]; 31 int b = SIZE_TABLE[mid + 1]; 32 if (size > b) { 33 low = mid + 1; 34 } else { 35 if (size >= a) { 36 if (size == a) { 37 return mid; 38 } 39 40 return mid + 1; 41 } 42 43 high = mid - 1; 44 } 45 } 46 47 return low; 48 } 49 50 public AdaptiveRecvByteBufAllocator() { 51 this(64, 2048, 65536); 52 } 53 54 public AdaptiveRecvByteBufAllocator(int minimum, int initial, int maximum) { 55 ObjectUtil.checkPositive(minimum, "minimum"); 56 //minimum不能大于初始化长度initial,初始化长度initial不能超过maximum 57 if (initial < minimum) { 58 throw new IllegalArgumentException("initial: " + initial); 59 } else if (maximum < initial) { 60 throw new IllegalArgumentException("maximum: " + maximum); 61 } else { 62 int minIndex = getSizeTableIndex(minimum); 63 if (SIZE_TABLE[minIndex] < minimum) { 64 this.minIndex = minIndex + 1; 65 } else { 66 this.minIndex = minIndex; 67 } 68 69 int maxIndex = getSizeTableIndex(maximum); 70 if (SIZE_TABLE[maxIndex] > maximum) { 71 this.maxIndex = maxIndex - 1; 72 } else { 73 this.maxIndex = maxIndex; 74 } 75 76 this.initial = initial; 77 } 78 } 79 80 public Handle newHandle() { 81 return new AdaptiveRecvByteBufAllocator.HandleImpl(this.minIndex, this.maxIndex, this.initial); 82 } 83 84 public AdaptiveRecvByteBufAllocator respectMaybeMoreData(boolean respectMaybeMoreData) { 85 super.respectMaybeMoreData(respectMaybeMoreData); 86 return this; 87 } 88 /* 89 分配了一个int类型的数组,并进行该数组的初始化处理,从实现来看,该数组的长度是53,前32位是16的倍数,value值是从16开始,到512;从第33位开始,值是前一位的两倍,即从1024、2048、到最大值1073741824 90 */ 91 static { 92 List<Integer> sizeTable = new ArrayList(); 93 94 int i; 95 for(i = 16; i < 512; i += 16) { 96 sizeTable.add(i); 97 } 98 99 for(i = 512; i > 0; i <<= 1) { 100 sizeTable.add(i); 101 } 102 103 SIZE_TABLE = new int[sizeTable.size()]; 104 105 for(i = 0; i < SIZE_TABLE.length; ++i) { 106 SIZE_TABLE[i] = (Integer)sizeTable.get(i); 107 } 108 109 DEFAULT = new AdaptiveRecvByteBufAllocator(); 110 } 111 112 private final class HandleImpl extends MaxMessageHandle { 113 private final int minIndex; 114 private final int maxIndex; 115 private int index;
//每次调容最关键的参数 116 private int nextReceiveBufferSize; 117 private boolean decreaseNow; 118 119 HandleImpl(int minIndex, int maxIndex, int initial) { 120 super(AdaptiveRecvByteBufAllocator.this); 121 this.minIndex = minIndex; 122 this.maxIndex = maxIndex;
//用initial获取一开始初始化缓冲的下标,在根据SIZE_TABLE查找应分配的BufferSize。 123 this.index = AdaptiveRecvByteBufAllocator.getSizeTableIndex(initial); 124 this.nextReceiveBufferSize = AdaptiveRecvByteBufAllocator.SIZE_TABLE[this.index]; 125 } 126 127 public void lastBytesRead(int bytes) { 128 if (bytes == this.attemptedBytesRead()) { 129 this.record(bytes); 130 } 131 132 super.lastBytesRead(bytes); 133 } 134 135 public int guess() { 136 return this.nextReceiveBufferSize; 137 } 138 /* 139 140 该方法的参数是一次读取操作中实际读取到的数据大小,将其与nextReceiveBufferSize 进行比较,如果实际字节数actualReadBytes大于等于该值,则立即更新nextReceiveBufferSize ,其更新后的值与INDEX_INCREMENT有关。INDEX_INCREMENT为默认常量,值为4。也就是说在扩容时会一次性增大多一些,以保证下次有足够空间可以接收数据。而相对扩容的策略,缩容策略则实际保守些,常量为INDEX_INCREMENT,值为1,同样也是进行对比, 但不同的是,若实际字节小于所用nextReceiveBufferSize,并不会立马进行大小调整,而是先把 decreaseNow 设置为true,如果下次仍然小于,则才会减少nextReceiveBufferSize的大小 141 */ 142 private void record(int actualReadBytes) { 143 if (actualReadBytes <= AdaptiveRecvByteBufAllocator.SIZE_TABLE[Math.max(0, this.index - 1)]) { 144 if (this.decreaseNow) { 145 this.index = Math.max(this.index - 1, this.minIndex); 146 this.nextReceiveBufferSize = AdaptiveRecvByteBufAllocator.SIZE_TABLE[this.index]; 147 this.decreaseNow = false; 148 } else { 149 this.decreaseNow = true; 150 } 151 } else if (actualReadBytes >= this.nextReceiveBufferSize) { 152 this.index = Math.min(this.index + 4, this.maxIndex); 153 this.nextReceiveBufferSize = AdaptiveRecvByteBufAllocator.SIZE_TABLE[this.index]; 154 this.decreaseNow = false; 155 } 156 157 } 158 159 public void readComplete() { 160 this.record(this.totalBytesRead()); 161 } 162 } 163 }