Xiong LIU created JCS-109:
-----------------------------

             Summary: poor performance of BlockDisk.write(Serializable object)
                 Key: JCS-109
                 URL: https://issues.apache.org/jira/browse/JCS-109
             Project: Commons JCS
          Issue Type: Improvement
    Affects Versions: jcs-2.0.0
            Reporter: Xiong LIU


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) {
                emptyBlock = numberOfBlocks.getAndIncrement();
            }
            blocks[i] = emptyBlock;
        }

        return blocks;
    }



--
This message was sent by Atlassian JIRA
(v6.1#6144)

Reply via email to