Stupid performance trick in Java

ByteBuffer has a compact() method which is useful for re-using a buffer if it is not full consumed. However, in the likely case it is consumed, it can perform surprising badly.

while (in.read(buf) >= 0 || buf.position != 0) {
     buf.flip();
     out.write(buf);
     buf.compact();    // In case of partial write
}

In my application, the throughput increased by 6% by replacing compact() with this method.

public static void compact(ByteBuffer bb) {
    if (bb.remaining() == 0)
        bb.clear();
    else
        bb.compact();
}

Note: this is not the increase in a micro-benchmark, but across the entire application!

Your Mileage May Vary of course

Comments

  1. I wonder whether your app does anything else (i.e. real IO). Tested on Windows with -server JVM: https://gist.github.com/1486476

    ReplyDelete
  2. What may not have been clear is that the ByteBuffer is typically empty. In this situation, calling clear() instead of compact() it makes a big difference.

    BTW: Using direct memory also appears to make more of a difference.

    private static long test(int[] writes, Compactor cn) {
    final ByteBuffer b = ByteBuffer.allocateDirect(PAGE);
    long written = 0;

    for (int i = 0; i < writes.length; ++i) {
    b.limit(i % PAGE);
    b.position(i % PAGE);
    cn.compact(b);
    }
    return written;
    }

    prints

    Run: 2

    norm : 906624000ns
    opt : 307983000ns
    Factor norm/opt : 2.944

    ReplyDelete

Post a Comment

Popular posts from this blog

Java is Very Fast, If You Don’t Create Many Objects

Low Latency Microservices, A Retrospective

Unusual Java: StackTrace Extends Throwable