Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Fixed
-
jcs-2.0-beta-1
-
None
Description
The performance of BlockDisk.write(Serializable object) is poor, because current implementation involves much ByteBuffer allocation and byte array allocation and memory copy.
The following is my implementation, which only needs to allocate HEADER_SIZE_BYTES. A benchmark can be done to show the performance gain.
protected int[] write(Serializable object) throws IOException {
// serialize the object
byte[] data = elementSerializer.serialize(object);
// figure out how many blocks we need.
int numBlocksNeeded = calculateTheNumberOfBlocksNeeded(data);
// allocate blocks
int[] blocks = allocateBlocks(numBlocksNeeded);
int offset = 0;
final int maxChunkSize = blockSizeBytes - HEADER_SIZE_BYTES;
ByteBuffer headerBuffer = ByteBuffer.allocate(HEADER_SIZE_BYTES);
for (int i = 0; i < numBlocksNeeded; i++)
{ headerBuffer.clear(); int length = Math.min(maxChunkSize, data.length - offset); headerBuffer.putInt(length); ByteBuffer dataBuffer = ByteBuffer.wrap(data, offset, length); long position = calculateByteOffsetForBlock(blocks[i]); // write the header headerBuffer.flip(); int written = fc.write(headerBuffer, position); assert written == HEADER_SIZE_BYTES; //write the data written = fc.write(dataBuffer, position + HEADER_SIZE_BYTES); assert written == length; offset += length; }fc.force(false);
return blocks;
}
private int[] allocateBlocks(int numBlocksNeeded) {
assert numBlocksNeeded >= 1;
int[] blocks = new int[numBlocksNeeded];
// get them from the empty list or take the next one
for (int i = 0; i < numBlocksNeeded; i++) {
Integer emptyBlock = emptyBlocks.takeFirst();
if (emptyBlock == null)
blocks[i] = emptyBlock;
}
return blocks;
}