Skip to content

Commit

Permalink
Merge pull request #18 from phraktle/perf-opt
Browse files Browse the repository at this point in the history
Inline and optimize some decoding methods to improve performance
  • Loading branch information
oschwald committed Dec 26, 2015
2 parents 9d2f4ed + 499cf42 commit 8a874ee
Showing 1 changed file with 27 additions and 38 deletions.
65 changes: 27 additions & 38 deletions src/main/java/com/maxmind/db/Decoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ final class Decoder {

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

private static final int[] POINTER_VALUE_OFFSETS = { 0, 0, 1 << 11, (1 << 19) + ((1) << 11), 0 };

// XXX - This is only for unit testings. We should possibly make a
// constructor to set this
boolean POINTER_TEST_HACK = false;
Expand Down Expand Up @@ -99,14 +101,19 @@ Result decode(int offset) throws IOException {
// use the size to determine the length of the pointer and then follow
// it.
if (type.equals(Type.POINTER)) {
Result pointer = this.decodePointer(ctrlByte, offset);
int pointerSize = ((ctrlByte >>> 3) & 0x3) + 1;
int base = pointerSize == 4 ? (byte) 0 : (byte) (ctrlByte & 0x7);
int packed = this.decodeInteger(base, pointerSize);
long pointer = packed + this.pointerBase + POINTER_VALUE_OFFSETS[pointerSize];
int newOffset = offset + pointerSize;

// for unit testing
if (this.POINTER_TEST_HACK) {
return pointer;
return new Result(new LongNode(pointer), newOffset);
}
Result result = this.decode((pointer.getNode().asInt()));
result.setOffset(pointer.getOffset());

Result result = this.decode((int) pointer);
result.setOffset(newOffset);
return result;
}

Expand All @@ -126,9 +133,22 @@ Result decode(int offset) throws IOException {
offset++;
}

int[] sizeArray = this.sizeFromCtrlByte(ctrlByte, offset);
int size = sizeArray[0];
offset = sizeArray[1];
int size = ctrlByte & 0x1f;
if (size >= 29) {
int bytesToRead = size - 28;
int i = this.decodeInteger(bytesToRead);
switch (size) {
case 29:
size = 29 + i;
break;
case 30:
size = 285 + i;
break;
default:
size = 65821 + (i & (0x0FFFFFFF >>> 32 - 8 * bytesToRead));
}
offset += bytesToRead;
}

return this.decodeByType(type, offset, size);
}
Expand Down Expand Up @@ -176,19 +196,6 @@ private Result decodeByType(Type type, int offset, int size)
}
}

private static final int[] POINTER_VALUE_OFFSETS = {0, 0, 1 << 11,
(1 << 19) + ((1) << 11), 0};

private Result decodePointer(int ctrlByte, int offset) {
int pointerSize = ((ctrlByte >>> 3) & 0x3) + 1;
int base = pointerSize == 4 ? (byte) 0 : (byte) (ctrlByte & 0x7);
int packed = this.decodeInteger(base, pointerSize);
long pointer = packed + this.pointerBase
+ POINTER_VALUE_OFFSETS[pointerSize];

return new Result(new LongNode(pointer), offset + pointerSize);
}

private String decodeString(int size) throws CharacterCodingException {
int oldLimit = buffer.limit();
buffer.limit(buffer.position() + size);
Expand Down Expand Up @@ -300,24 +307,6 @@ private Result decodeMap(int size, int offset) throws IOException {
return new Result(map, offset);
}

private int[] sizeFromCtrlByte(int ctrlByte, int offset) {
int size = ctrlByte & 0x1f;
int bytesToRead = size < 29 ? 0 : size - 28;

if (size == 29) {
int i = this.decodeInteger(bytesToRead);
size = 29 + i;
} else if (size == 30) {
int i = this.decodeInteger(bytesToRead);
size = 285 + i;
} else if (size > 30) {
int i = this.decodeInteger(bytesToRead)
& (0x0FFFFFFF >>> (32 - (8 * bytesToRead)));
size = 65821 + i;
}
return new int[]{size, offset + bytesToRead};
}

private byte[] getByteArray(int length) {
return Decoder.getByteArray(this.buffer, length);
}
Expand Down

0 comments on commit 8a874ee

Please sign in to comment.