Suggestion for some refactorying for MemoryBuffer class.
pushrsp opened this issue · comments
Can i do some refactor for MemoryBuffer
class?
e.g
public void writeBoolean(boolean value) {
final int writerIdx = writerIndex;
final int newIdx = writerIdx + 1; // we can replace this number to static variable which make more understandable.
ensure(newIdx);
final long pos = address + writerIdx;
UNSAFE.putByte(heapMemory, pos, (byte) (value ? 1 : 0));
writerIndex = newIdx;
}
public byte readByte() {
int readerIdx = readerIndex;
// every readX method use this for checking bound, so we can make short for it.
if (BoundsChecking.BOUNDS_CHECKING_ENABLED && readerIdx > size - 1) {
throw new IndexOutOfBoundsException(
String.format(
"readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx, 1, size, this));
}
readerIndex = readerIdx + 1;
return UNSAFE.getByte(heapMemory, address + readerIdx);
}
Hi @pushrsp ,thanks for your suggession.
Regarding your first proposal, I think it is unnecessary, we use one byte to store the value of boolean type. We can also know it from the code UNSAFE.putByte(heapMemory, pos, (byte) (value ? 1 : 0));
below, so writerIdx + 1
itself is easy to understand.
Regarding the second suggestion, how to simplify it? Extract a function separately for the checked logic and call it in readXXX?
cc @chaokunyang
Regarding the second suggestion, how to simplify it? Extract a function separately for the checked logic and call it in readXXX?
i would simplify like this below.
public byte readByte() {
int readerIdx = readerIndex;
throwIfOutOfBound(readerIdx, 1);
readerIndex = readerIdx + 1;
return UNSAFE.getByte(heapMemory, address + readerIdx);
}
public short readShort() {
int readerIdx = readerIndex;
throwIfOutOfBound(readerIdx, 2)
readerIndex = readerIdx + 2;
final long pos = address + readerIdx;
if (LITTLE_ENDIAN) {
return UNSAFE.getShort(heapMemory, pos);
} else {
return Short.reverseBytes(UNSAFE.getShort(heapMemory, pos));
}
}
...
private void throwIfOutOfBound(int readerIdx, int dataSize) {
if(BoundsChecking.BOUNDS_CHECKING_ENABLED && readerIdx > size - dataSize) {
throw new IndexOutOfBoundsException(
String.format(
"readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx, dataSize, size, this));
}
}
LGTM.
We don't have to worry about throwIfOutOfBound
function not being inlined because throwIfOutOfBound
is rarely executed.
BTW, we can also use throwIndexOutOfBoundsException function to replace throw new IndexOutOfBoundsException(...)
.
What do you think about this suggestion? @chaokunyang
I refactorized this code, it has been replaced by a StreamReader
in pr #1451 .
For changes here, seems throwIfOutOfBound will be invoked every time. The method invocation is not ignorable in such primitives. Jvm inline doesn't happens sometimes.