Skip to content

Instantly share code, notes, and snippets.

@ennerf
Created June 18, 2015 22:44
Show Gist options
  • Save ennerf/45809ef405a4a56a285b to your computer and use it in GitHub Desktop.
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)
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