Created
June 18, 2015 22:44
-
-
Save ennerf/45809ef405a4a56a285b to your computer and use it in GitHub Desktop.
Benchmark of Protobuf JavaNano writeRawLittleEndian32 and writeRawVarint32 using byte[] (old) and ByteBuffer (new)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package us.hebi.protocol.nano; | |
import org.openjdk.jmh.annotations.*; | |
import org.openjdk.jmh.runner.Runner; | |
import org.openjdk.jmh.runner.RunnerException; | |
import org.openjdk.jmh.runner.options.Options; | |
import org.openjdk.jmh.runner.options.OptionsBuilder; | |
import org.openjdk.jmh.runner.options.VerboseMode; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.util.concurrent.TimeUnit; | |
/** | |
* @author Florian Enner < florian @ hebirobotics.com > | |
* @since 12 Sep 2014 | |
*/ | |
@BenchmarkMode(Mode.AverageTime) | |
@OutputTimeUnit(TimeUnit.MICROSECONDS) | |
@Fork(2) | |
@Warmup(iterations = 5) | |
@Measurement(iterations = 5) | |
@State(Scope.Thread) | |
public class BufferWriteBenchmark { | |
public static void main(String[] args) throws RunnerException { | |
Options options = new OptionsBuilder() | |
.include(".*" + BufferWriteBenchmark.class.getSimpleName() + ".*") | |
.verbosity(VerboseMode.NORMAL) | |
.build(); | |
new Runner(options).run(); | |
} | |
/* | |
Benchmark Mode Samples Score Score error Units | |
u.h.p.n.BufferWriteBenchmark.writeRawLittleEndian32_array avgt 10 0.235 0.006 us/op | |
u.h.p.n.BufferWriteBenchmark.writeRawLittleEndian32_byteBuffer avgt 10 0.279 0.012 us/op | |
u.h.p.n.BufferWriteBenchmark.writeRawLittleEndian32_directBuffer avgt 10 0.146 0.004 us/op | |
u.h.p.n.BufferWriteBenchmark.writeRawVarint32_array avgt 10 1.083 0.030 us/op | |
u.h.p.n.BufferWriteBenchmark.writeRawVarint32_byteBuffer avgt 10 1.535 0.026 us/op | |
u.h.p.n.BufferWriteBenchmark.writeRawVarint32_directBuffer avgt 10 1.320 0.029 us/op | |
*/ | |
int value; | |
OutputBuffer arrayBuffer; | |
OutputBuffer byteBuffer; | |
OutputBuffer directBuffer; | |
final static int capacity = 512; | |
@Setup | |
public void setup() { | |
value = 1 << 9; // results in 2 varint bytes | |
arrayBuffer = new ArrayOutputBuffer(new byte[capacity]); | |
byteBuffer = new ByteBufferOutput(ByteBuffer.allocate(capacity)); | |
directBuffer = new ByteBufferOutput(ByteBuffer.allocateDirect(capacity)); | |
} | |
@Benchmark | |
public int writeRawVarint32_array() { | |
return writeRawVarint32(arrayBuffer); | |
} | |
@Benchmark | |
public int writeRawVarint32_byteBuffer() { | |
return writeRawVarint32(byteBuffer); | |
} | |
@Benchmark | |
public int writeRawVarint32_directBuffer() { | |
return writeRawVarint32(directBuffer); | |
} | |
@Benchmark | |
public int writeRawLittleEndian32_array() { | |
return writeRawLittleEndian32(arrayBuffer); | |
} | |
@Benchmark | |
public int writeRawLittleEndian32_byteBuffer() { | |
return writeRawLittleEndian32(byteBuffer); | |
} | |
@Benchmark | |
public int writeRawLittleEndian32_directBuffer() { | |
return writeRawLittleEndian32(directBuffer); | |
} | |
int writeRawLittleEndian32(final OutputBuffer buffer) { | |
buffer.reset(); | |
while (buffer.remaining() > 0) { | |
buffer.writeRawLittleEndian32(value); | |
} | |
return buffer.remaining(); | |
} | |
int writeRawVarint32(final OutputBuffer buffer) { | |
buffer.reset(); | |
while (buffer.remaining() > 0) { | |
buffer.writeRawVarint32(value); | |
} | |
return buffer.remaining(); | |
} | |
interface OutputBuffer { | |
/** | |
* Encode and write a varint. {@code value} is treated as | |
* unsigned, so it won't be sign-extended if negative. | |
*/ | |
void writeRawVarint32(int value); | |
/** | |
* Write a little-endian 32-bit integer. | |
*/ | |
void writeRawLittleEndian32(int value); | |
int remaining(); | |
void reset(); | |
} | |
static class ArrayOutputBuffer implements OutputBuffer { | |
public void writeRawVarint32(int value) { | |
while (true) { | |
if ((value & ~0x7F) == 0) { | |
writeRawByte(value); | |
return; | |
} else { | |
writeRawByte((value & 0x7F) | 0x80); | |
value >>>= 7; | |
} | |
} | |
} | |
public void writeRawLittleEndian32(final int value) { | |
writeRawByte((value) & 0xFF); | |
writeRawByte((value >> 8) & 0xFF); | |
writeRawByte((value >> 16) & 0xFF); | |
writeRawByte((value >> 24) & 0xFF); | |
} | |
void writeRawByte(int value) { | |
buffer[position++] = (byte) value; | |
} | |
@Override | |
public int remaining() { | |
return buffer.length - position; | |
} | |
@Override | |
public void reset() { | |
position = 0; | |
} | |
ArrayOutputBuffer(byte[] buffer) { | |
this.buffer = buffer; | |
} | |
final byte[] buffer; | |
int position = 0; | |
} | |
static class ByteBufferOutput implements OutputBuffer { | |
@Override | |
public void writeRawVarint32(int value) { | |
while (true) { | |
if ((value & ~0x7F) == 0) { | |
writeRawByte(value); | |
return; | |
} else { | |
writeRawByte((value & 0x7F) | 0x80); | |
value >>>= 7; | |
} | |
} | |
} | |
@Override | |
public void writeRawLittleEndian32(final int value) { | |
buffer.putInt(value); | |
} | |
void writeRawByte(final int value) { | |
buffer.put((byte) value); | |
} | |
@Override | |
public int remaining() { | |
return buffer.remaining(); | |
} | |
@Override | |
public void reset() { | |
buffer.position(0); | |
} | |
ByteBufferOutput(ByteBuffer buffer) { | |
this.buffer = buffer; | |
buffer.order(ByteOrder.LITTLE_ENDIAN); | |
} | |
final ByteBuffer buffer; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment