| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.cassandra.test.microbench; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.RandomAccessFile; |
| import java.nio.ByteBuffer; |
| import java.nio.channels.FileChannel; |
| import java.nio.channels.WritableByteChannel; |
| import java.util.PrimitiveIterator; |
| import java.util.Random; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.apache.cassandra.io.util.BufferedDataOutputStreamPlus; |
| import org.apache.cassandra.io.util.DataOutputPlus; |
| import org.apache.cassandra.utils.vint.VIntCoding; |
| import org.openjdk.jmh.annotations.Benchmark; |
| import org.openjdk.jmh.annotations.BenchmarkMode; |
| import org.openjdk.jmh.annotations.Fork; |
| import org.openjdk.jmh.annotations.Measurement; |
| import org.openjdk.jmh.annotations.Mode; |
| import org.openjdk.jmh.annotations.OutputTimeUnit; |
| import org.openjdk.jmh.annotations.Param; |
| import org.openjdk.jmh.annotations.Scope; |
| import org.openjdk.jmh.annotations.State; |
| import org.openjdk.jmh.annotations.TearDown; |
| import org.openjdk.jmh.annotations.Threads; |
| import org.openjdk.jmh.annotations.Warmup; |
| import org.openjdk.jmh.infra.Blackhole; |
| |
| @BenchmarkMode(Mode.AverageTime) |
| @OutputTimeUnit(TimeUnit.NANOSECONDS) |
| @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) |
| @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) |
| @Fork(value = 3, jvmArgsAppend = "-Xmx512M") |
| @Threads(1) |
| @State(Scope.Benchmark) |
| public class VIntCodingBench |
| { |
| long oneByte = 53; |
| long twoBytes = 10201; |
| long threeBytes = 1097151L; |
| long fourBytes = 168435455L; |
| long fiveBytes = 33251130335L; |
| long sixBytes = 3281283447775L; |
| long sevenBytes = 417672546086779L; |
| long eightBytes = 52057592037927932L; |
| long nineBytes = 72057594037927937L; |
| |
| final static String MONOMORPHIC = "monomorphic"; |
| final static String BIMORPHIC = "bimorphic"; |
| final static String MEGAMORPHIC = "megamorphic"; |
| |
| @Param({ MONOMORPHIC, BIMORPHIC, MEGAMORPHIC}) |
| String allocation; |
| |
| final Random random = new Random(100); |
| final PrimitiveIterator.OfLong longs = random.longs().iterator(); |
| final static int BUFFER_SIZE = 8192; |
| |
| ByteBuffer onheap = ByteBuffer.allocate(BUFFER_SIZE); |
| ByteBuffer direct = ByteBuffer.allocateDirect(BUFFER_SIZE); |
| File mmapedFile = new File(VIntCodingBench.class + "_mmap"); |
| ByteBuffer mmaped = allocateMmapedByteBuffer(mmapedFile, BUFFER_SIZE); |
| |
| @TearDown |
| public void tearDown() |
| { |
| mmapedFile.delete(); |
| } |
| |
| private static ByteBuffer allocateMmapedByteBuffer(File mmapFile, int bufferSize) |
| { |
| try(RandomAccessFile file = new RandomAccessFile(mmapFile, "rw"); |
| FileChannel ch = file.getChannel()) |
| { |
| return ch.map(FileChannel.MapMode.READ_WRITE, 0, bufferSize); |
| } |
| catch (IOException e) |
| { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| private ByteBuffer getByteBuffer(String allocation) |
| { |
| ByteBuffer buffer; |
| if (allocation.equals(MONOMORPHIC)) |
| { |
| buffer = onheap; |
| } |
| else if (allocation.equals(BIMORPHIC)) |
| { |
| buffer = random.nextBoolean() ? onheap : direct; |
| } |
| else |
| { |
| switch(random.nextInt(3)) |
| { |
| case 0: |
| buffer = onheap; |
| break; |
| case 1: |
| buffer = direct; |
| break; |
| default: |
| buffer = mmaped; |
| break; |
| } |
| } |
| return buffer; |
| } |
| |
| private DataOutputPlus getBufferedDataOutput(Blackhole bh, ByteBuffer buffer) |
| { |
| WritableByteChannel wbc = new WritableByteChannel() { |
| |
| @Override |
| public boolean isOpen() |
| { |
| return true; |
| } |
| |
| @Override |
| public void close() throws IOException |
| { |
| } |
| |
| @Override |
| public int write(ByteBuffer src) throws IOException |
| { |
| bh.consume(src); |
| int remaining = src.remaining(); |
| src.position(src.limit()); |
| return remaining; |
| } |
| }; |
| return new BufferedDataOutputStreamPlus(wbc, buffer); |
| } |
| |
| @Benchmark |
| public void testWrite1ByteBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(oneByte, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite1ByteDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(oneByte, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite2BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(twoBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite2BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(twoBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite3BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(threeBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite3BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(threeBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite4BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(fourBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite4BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(fourBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite5BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(fiveBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite5BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(fiveBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite6BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(sixBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite6BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(sixBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite7BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(sevenBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite7BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(sevenBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite8BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(eightBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite8BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(eightBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite9BytesBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(nineBytes, buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWrite9BytesDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(nineBytes, out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWriteRandomLongBB(final Blackhole bh) |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| VIntCoding.writeUnsignedVInt(longs.nextLong(), buffer); |
| bh.consume(buffer); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testWriteRandomLongDOP(final Blackhole bh) throws IOException |
| { |
| ByteBuffer buffer = getByteBuffer(allocation); |
| DataOutputPlus out = getBufferedDataOutput(bh, buffer); |
| VIntCoding.writeUnsignedVInt(longs.nextLong(), out); |
| bh.consume(out); |
| buffer.clear(); |
| } |
| |
| @Benchmark |
| public void testComputeUnsignedVIntSize(final Blackhole bh) |
| { |
| bh.consume(VIntCoding.computeUnsignedVIntSize(longs.nextLong())); |
| } |
| } |