Optimize PoolChunk

- Using short[] for memoryMap did not improve performance. Reverting
  back to the original dual-byte[] structure in favor of simplicity.
- Optimize allocateRun() which yields small performence improvement
- Use local variable when member fields are accessed more than once
This commit is contained in:
Trustin Lee 2014-06-26 17:00:52 +09:00
parent dbc011c3f4
commit c0462c0c3b

View File

@ -103,14 +103,12 @@ package io.netty.buffer;
final class PoolChunk<T> { final class PoolChunk<T> {
private static final int BYTE_LENGTH = Byte.SIZE;
private static final int UPPER_BYTE_MASK = - (1 << BYTE_LENGTH);
final PoolArena<T> arena; final PoolArena<T> arena;
final T memory; final T memory;
final boolean unpooled; final boolean unpooled;
private final short[] memoryMap; private final byte[] memoryMap;
private final byte[] depthMap;
private final PoolSubpage<T>[] subpages; private final PoolSubpage<T>[] subpages;
/** Used to determine if the requested capacity is equal to or greater than pageSize. */ /** Used to determine if the requested capacity is equal to or greater than pageSize. */
private final int subpageOverflowMask; private final int subpageOverflowMask;
@ -145,19 +143,20 @@ final class PoolChunk<T> {
subpageOverflowMask = ~(pageSize - 1); subpageOverflowMask = ~(pageSize - 1);
freeBytes = chunkSize; freeBytes = chunkSize;
assert maxOrder < 30 : "maxOrder should be < 30, but is : " + maxOrder; assert maxOrder < 30 : "maxOrder should be < 30, but is: " + maxOrder;
maxSubpageAllocs = 1 << maxOrder; maxSubpageAllocs = 1 << maxOrder;
// Generate the memory map. // Generate the memory map.
memoryMap = new short[maxSubpageAllocs << 1]; memoryMap = new byte[maxSubpageAllocs << 1];
depthMap = new byte[memoryMap.length];
int memoryMapIndex = 1; int memoryMapIndex = 1;
for (int d = 0; d <= maxOrder; ++d) { // move down the tree one level at a time for (int d = 0; d <= maxOrder; ++ d) { // move down the tree one level at a time
short dd = (short) (d << BYTE_LENGTH | d);
int depth = 1 << d; int depth = 1 << d;
for (int p = 0; p < depth; ++p) { for (int p = 0; p < depth; ++ p) {
// in each level traverse left to right and set value to the depth of subtree // in each level traverse left to right and set value to the depth of subtree
memoryMap[memoryMapIndex] = dd; memoryMap[memoryMapIndex] = (byte) d;
memoryMapIndex += 1; depthMap[memoryMapIndex] = (byte) d;
memoryMapIndex ++;
} }
} }
@ -170,6 +169,7 @@ final class PoolChunk<T> {
this.arena = arena; this.arena = arena;
this.memory = memory; this.memory = memory;
memoryMap = null; memoryMap = null;
depthMap = null;
subpages = null; subpages = null;
subpageOverflowMask = 0; subpageOverflowMask = 0;
pageSize = 0; pageSize = 0;
@ -187,6 +187,7 @@ final class PoolChunk<T> {
} }
int usage() { int usage() {
final int freeBytes = this.freeBytes;
if (freeBytes == 0) { if (freeBytes == 0) {
return 100; return 100;
} }
@ -288,8 +289,7 @@ final class PoolChunk<T> {
* @return index in memoryMap * @return index in memoryMap
*/ */
private long allocateRun(int normCapacity) { private long allocateRun(int normCapacity) {
int numPages = normCapacity >>> pageShifts; int d = maxOrder - (log2(normCapacity) - pageShifts);
int d = maxOrder - log2(numPages);
int id = allocateNode(d); int id = allocateNode(d);
if (id < 0) { if (id < 0) {
return id; return id;
@ -311,6 +311,10 @@ final class PoolChunk<T> {
if (id < 0) { if (id < 0) {
return id; return id;
} }
final PoolSubpage<T>[] subpages = this.subpages;
final int pageSize = this.pageSize;
freeBytes -= pageSize; freeBytes -= pageSize;
int subpageIdx = subpageIdx(id); int subpageIdx = subpageIdx(id);
@ -379,16 +383,15 @@ final class PoolChunk<T> {
} }
private byte value(int id) { private byte value(int id) {
return (byte) memoryMap[id]; return memoryMap[id];
} }
private void setValue(int id, byte val) { private void setValue(int id, byte val) {
memoryMap[id] = (short) (memoryMap[id] & UPPER_BYTE_MASK | val); memoryMap[id] = val;
} }
private byte depth(int id) { private byte depth(int id) {
short val = memoryMap[id]; return depthMap[id];
return (byte) (val >>> BYTE_LENGTH);
} }
private static int log2(int val) { private static int log2(int val) {