Last active
November 16, 2015 04:17
-
-
Save seraphy/6276dbae1eb4ee96325d to your computer and use it in GitHub Desktop.
jmhマイクロベンチマークツールを使った、ヒープおよびダイレクトのByteBufferのバイトオーダによるパフォーマンスの違いの比較、および、Unsafeによる配列のアクセスパフォーマンスとの比較。
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 jp.seraphyware.jmhexample; | |
import java.lang.reflect.Field; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.nio.IntBuffer; | |
import java.util.concurrent.TimeUnit; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.Level; | |
import org.openjdk.jmh.annotations.Mode; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.Setup; | |
import org.openjdk.jmh.annotations.State; | |
import org.openjdk.jmh.annotations.TearDown; | |
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.TimeValue; | |
/** | |
* ベンチマーク定義クラス. | |
* | |
* メソッドにBenchmarkアノテーションをつけておくとベンチマークメソッドと認識される. | |
* (jUnit4みたいな感じ.) | |
* | |
* mvn clean package でビルドしたのち、 | |
* target上で、java -jar benchmarks.jar | |
* でベンチマークを一括実行する. | |
* (指定できるベンチマークオプションの詳細は -h オプションで表示できる) | |
* (IDEから実行する場合は本クラスのmainメソッドの説明を参照のこと) | |
* | |
* @author seraphy | |
*/ | |
public class BufferAccessBenchmark { | |
/** | |
* テスト中にスレッドごとベンチマークごとの状態を保持するインスタンス. | |
* | |
* @author seraphy | |
*/ | |
@State(Scope.Thread) | |
protected static class BenchContextBase { | |
/** | |
* バイトオーダー | |
*/ | |
private final ByteOrder byteOrder; | |
/** | |
* ヒープ | |
*/ | |
private byte[] data; | |
/** | |
* ヒープをラップしたバッファ | |
*/ | |
private ByteBuffer bufHeap; | |
/** | |
* ダイレクトバッファ | |
*/ | |
private ByteBuffer bufDirect; | |
/** | |
* アンセーフ | |
*/ | |
@SuppressWarnings("restriction") | |
private sun.misc.Unsafe unsafe; | |
/** | |
* バイトオーダを指定して構築する. | |
* @param byteOrder | |
*/ | |
protected BenchContextBase(ByteOrder byteOrder) { | |
this.byteOrder = byteOrder; | |
} | |
/** | |
* データの初期化. | |
* Trialの場合、スレッドごとベンチマークの開始ごとに一度呼び出される.<br> | |
* (ウォームアップイテレーション、および計測イテレーション中には呼び出されない。) | |
* (Trialがデフォルト、そのほかにIteration, Invocationが指定可能.) | |
*/ | |
@Setup(Level.Trial) | |
public void setup() { | |
// ヒープ上にデータを作成する | |
byte[] data = new byte[512 * 1024]; // 512kb | |
this.data = data; | |
// ヒープ上のByteBufferを作成する. | |
bufHeap = ByteBuffer.wrap(data); | |
bufHeap.order(byteOrder); | |
// ※ テストデータを作成する | |
initData(bufHeap); | |
// ダイレクトメモリを確保してByteBufferを作成する | |
// (データはヒープのものをコピーする) | |
bufDirect = ByteBuffer.allocateDirect(data.length); | |
bufDirect.order(byteOrder); | |
bufDirect.put(data); | |
// アンセーフをリフレクション経由で取得する. | |
initUnsafe(); | |
} | |
/** | |
* アンセーフをリフレクションによって取得する. | |
*/ | |
@SuppressWarnings("restriction") | |
private void initUnsafe() { | |
try { | |
Field field = sun.misc.Unsafe.class | |
.getDeclaredField("theUnsafe"); | |
field.setAccessible(true); | |
unsafe = (sun.misc.Unsafe) field.get(null); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* データを初期化する. | |
* @param buf | |
*/ | |
private void initData(ByteBuffer buf) { | |
IntBuffer intBuf = buf.asIntBuffer(); | |
long total = 0; | |
for (int idx = 0; idx < data.length / 4; idx++) { | |
intBuf.put(idx); | |
total += idx; | |
} | |
//System.out.println("★total=" + total); | |
if (total != 8589869056L) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* スレッドごとベンチマーク終了ごとに呼び出される. | |
*/ | |
@TearDown | |
public void teardown() { | |
} | |
/** | |
* データが格納されているヒープを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public byte[] getData() { | |
return data; | |
} | |
/** | |
* ヒープをラップしているByteBufferを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public ByteBuffer getHeapByteBuffer() { | |
return bufHeap; | |
} | |
/** | |
* ダイレクトバッファを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public ByteBuffer getDirectByteBuffer() { | |
return bufDirect; | |
} | |
/** | |
* アンセーフを取得する. | |
* @return | |
*/ | |
@SuppressWarnings("restriction") | |
public sun.misc.Unsafe getUnsafe() { | |
return unsafe; | |
} | |
} | |
/** | |
* データの並びがLittleEndianのバッファをもつテストデータを作成する. | |
*/ | |
public static class BenchContextLE extends BenchContextBase { | |
public BenchContextLE() { | |
super(ByteOrder.LITTLE_ENDIAN); // Unsafe(intel)にあわせる | |
} | |
} | |
/** | |
* データの並びがBigEndianのバッファをもつテストデータを作成する. | |
*/ | |
public static class BenchContextBE extends BenchContextBase { | |
public BenchContextBE() { | |
super(ByteOrder.BIG_ENDIAN); // JAVA標準にあわせる | |
} | |
} | |
/** | |
* バイトバッファからint値を読み出すテスト | |
* @param buf | |
*/ | |
private static void runByteBuffer(ByteBuffer buf) { | |
buf.rewind(); | |
int limit = buf.limit(); | |
long total = 0; | |
while (buf.position() < limit) { | |
total += buf.getInt(); | |
} | |
if (total != 8589869056L) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* ヒープからUnsafeを使ってint値を読み出すテスト | |
* @param unsafe | |
* @param data | |
*/ | |
@SuppressWarnings("restriction") | |
private static void runUnsafe(sun.misc.Unsafe unsafe, byte[] data) { | |
int offset = sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; | |
int len = data.length + offset; | |
int pos = offset; | |
long total = 0; | |
while (pos < len) { | |
total += unsafe.getInt(data, (long) pos); | |
pos += 4; | |
} | |
if (total != 8589869056L) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* LittleEndianのデータをヒープ上のバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testHeapByteBufferLE(BenchContextLE ctx) { | |
runByteBuffer(ctx.getHeapByteBuffer()); | |
} | |
/** | |
* LittleEndianのデータをダイレクトバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testDirectByteBufferLE(BenchContextLE ctx) { | |
runByteBuffer(ctx.getDirectByteBuffer()); | |
} | |
/** | |
* LittleEndianのデータをアンセーフを使って読み出すベンチマーク | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testUnsafeLE(BenchContextLE ctx) { | |
runUnsafe(ctx.getUnsafe(), ctx.getData()); | |
} | |
/** | |
* BigEndianのデータをヒープ上のバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testHeapByteBufferBE(BenchContextBE ctx) { | |
runByteBuffer(ctx.getHeapByteBuffer()); | |
} | |
/** | |
* BigEndianのデータをダイレクトバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testDirectByteBufferBE(BenchContextBE ctx) { | |
runByteBuffer(ctx.getDirectByteBuffer()); | |
} | |
@Benchmark | |
public void testHeapByteArray(BenchContextLE ctx) { | |
byte[] data = ctx.getData(); | |
int len = data.length; | |
int pos = 0; | |
long total = 0; | |
while (pos < len) { | |
total += ((data[pos + 3] & 0xFF) << 24) | |
| ((data[pos + 2] & 0xFF) << 16) | |
| ((data[pos + 1] & 0xFF) << 8) | |
| (data[pos + 0] & 0xFF); | |
pos += 4; | |
} | |
if (total != 8589869056L) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* IDEから実行する場合は、 | |
* まず先にmvn package等を実行してサポートファイル類を生成しておく必要がある. | |
* (少なくともクラスまたはメソッドのシグネチャを変更追加するたびにmvnでビルドする必要がある。) | |
* その後、IDEから、このメイン関数を呼び出すことができるようになる. | |
* @param args | |
* @throws RunnerException | |
*/ | |
public static void main(String[] args) throws RunnerException { | |
Options opt = new OptionsBuilder() | |
// 実行すべきベンチマークが定義された"クラス名.メソッド名"を正規表現で指定 | |
.include(BufferAccessBenchmark.class.getSimpleName()) | |
// ウォームアップイテレーション数 "-wi"オプションに相当 | |
.warmupIterations(20) | |
// イテレーション数 "-i"オプションに相当 | |
.measurementIterations(10) | |
// フォーク数 "-f"オプションに相当 | |
.forks(1) | |
// 1回のテストメソッド実行時間 "-r"オプションに相当 | |
.measurementTime(TimeValue.seconds(1)) | |
// 同時実行スレッド数 (1測定毎のスレッド数 (サンプル数が増える)) | |
// .threads(Math.max(1, Runtime.getRuntime().availableProcessors() / 2)) | |
// 測定するモード = スループット | |
.timeUnit(TimeUnit.MICROSECONDS) | |
.mode(Mode.SampleTime) | |
.build(); | |
new Runner(opt).run(); | |
} | |
} |
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 jp.seraphyware.jmhexample; | |
import java.lang.reflect.Field; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.nio.FloatBuffer; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.Level; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.Setup; | |
import org.openjdk.jmh.annotations.State; | |
import org.openjdk.jmh.annotations.TearDown; | |
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.TimeValue; | |
/** | |
* ベンチマーク定義クラス2. | |
* | |
* @author seraphy | |
*/ | |
public class BufferAccessBenchmark2 { | |
/** | |
* テスト中にスレッドごとベンチマークごとの状態を保持するインスタンス. | |
* | |
* @author seraphy | |
*/ | |
@State(Scope.Thread) | |
protected static class BenchContextBase { | |
/** | |
* バイトオーダー | |
*/ | |
private final ByteOrder byteOrder; | |
/** | |
* ヒープ | |
*/ | |
private byte[] data; | |
/** | |
* ヒープをラップしたバッファ | |
*/ | |
private ByteBuffer bufHeap; | |
/** | |
* ダイレクトバッファ | |
*/ | |
private ByteBuffer bufDirect; | |
/** | |
* アンセーフ | |
*/ | |
@SuppressWarnings("restriction") | |
private sun.misc.Unsafe unsafe; | |
/** | |
* バイトオーダを指定して構築する. | |
* @param byteOrder | |
*/ | |
protected BenchContextBase(ByteOrder byteOrder) { | |
this.byteOrder = byteOrder; | |
} | |
/** | |
* データの初期化. | |
* Trialの場合、スレッドごとベンチマークの開始ごとに一度呼び出される.<br> | |
* (ウォームアップイテレーション、および計測イテレーション中には呼び出されない。) | |
* (Trialがデフォルト、そのほかにIteration, Invocationが指定可能.) | |
*/ | |
@Setup(Level.Trial) | |
public void setup() { | |
// ヒープ上にデータを作成する | |
byte[] data = new byte[512 * 1024]; // 512kb | |
this.data = data; | |
// ヒープ上のByteBufferを作成する. | |
bufHeap = ByteBuffer.wrap(data); | |
bufHeap.order(byteOrder); | |
// ※ テストデータを作成する | |
initData(bufHeap); | |
// byte[] tmp = new byte[8]; | |
// System.arraycopy(data, 0, tmp, 0, tmp.length); | |
// System.out.println("◆" + DatatypeConverter.printHexBinary(tmp)); | |
// ダイレクトメモリを確保してByteBufferを作成する | |
// (データはヒープのものをコピーする) | |
bufDirect = ByteBuffer.allocateDirect(data.length); | |
bufDirect.order(byteOrder); | |
bufDirect.put(data); | |
// アンセーフをリフレクション経由で取得する. | |
initUnsafe(); | |
} | |
/** | |
* アンセーフをリフレクションによって取得する. | |
*/ | |
@SuppressWarnings("restriction") | |
private void initUnsafe() { | |
try { | |
Field field = sun.misc.Unsafe.class | |
.getDeclaredField("theUnsafe"); | |
field.setAccessible(true); | |
unsafe = (sun.misc.Unsafe) field.get(null); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* データを初期化する. | |
* @param buf | |
*/ | |
private void initData(ByteBuffer buf) { | |
FloatBuffer intBuf = buf.asFloatBuffer(); | |
double total = 0; | |
for (int idx = 0; idx < data.length / 4; idx++) { | |
intBuf.put((float) idx); | |
total += idx; | |
} | |
//System.out.println("★total=" + total); | |
if (total != 8589869056L) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* スレッドごとベンチマーク終了ごとに呼び出される. | |
*/ | |
@TearDown | |
public void teardown() { | |
} | |
/** | |
* データが格納されているヒープを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public byte[] getData() { | |
return data; | |
} | |
/** | |
* ヒープをラップしているByteBufferを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public ByteBuffer getHeapByteBuffer() { | |
return bufHeap; | |
} | |
/** | |
* ダイレクトバッファを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public ByteBuffer getDirectByteBuffer() { | |
return bufDirect; | |
} | |
/** | |
* アンセーフを取得する. | |
* @return | |
*/ | |
@SuppressWarnings("restriction") | |
public sun.misc.Unsafe getUnsafe() { | |
return unsafe; | |
} | |
} | |
/** | |
* データの並びがLittleEndianのバッファをもつテストデータを作成する. | |
*/ | |
public static class BenchContextLE extends BenchContextBase { | |
public BenchContextLE() { | |
super(ByteOrder.LITTLE_ENDIAN); // Unsafe(intel)にあわせる | |
} | |
} | |
/** | |
* データの並びがBigEndianのバッファをもつテストデータを作成する. | |
*/ | |
public static class BenchContextBE extends BenchContextBase { | |
public BenchContextBE() { | |
super(ByteOrder.BIG_ENDIAN); // JAVA標準にあわせる | |
} | |
} | |
/** | |
* バイトバッファからint値を読み出すテスト | |
* @param buf | |
*/ | |
private static void runByteBuffer(ByteBuffer buf) { | |
buf.rewind(); | |
int limit = buf.limit(); | |
double total = 0; | |
while (buf.position() < limit) { | |
total += buf.getFloat(); | |
} | |
if (total != 8589869056L) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* ヒープからUnsafeを使ってint値を読み出すテスト | |
* @param unsafe | |
* @param data | |
*/ | |
@SuppressWarnings("restriction") | |
private static void runUnsafe(sun.misc.Unsafe unsafe, byte[] data) { | |
int offset = sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; | |
int len = data.length + offset; | |
int pos = offset; | |
double total = 0; | |
while (pos < len) { | |
total += unsafe.getFloat(data, (long) pos); | |
pos += 4; | |
} | |
if (total != 8589869056L) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* LittleEndianのデータをヒープ上のバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testHeapByteBufferLE(BenchContextLE ctx) { | |
runByteBuffer(ctx.getHeapByteBuffer()); | |
} | |
/** | |
* LittleEndianのデータをダイレクトバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testDirectByteBufferLE(BenchContextLE ctx) { | |
runByteBuffer(ctx.getDirectByteBuffer()); | |
} | |
/** | |
* LittleEndianのデータをアンセーフを使って読み出すベンチマーク | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testUnsafeLE(BenchContextLE ctx) { | |
runUnsafe(ctx.getUnsafe(), ctx.getData()); | |
} | |
/** | |
* BigEndianのデータをヒープ上のバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testHeapByteBufferBE(BenchContextBE ctx) { | |
runByteBuffer(ctx.getHeapByteBuffer()); | |
} | |
/** | |
* BigEndianのデータをダイレクトバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testDirectByteBufferBE(BenchContextBE ctx) { | |
runByteBuffer(ctx.getDirectByteBuffer()); | |
} | |
/** | |
* IDEから実行する場合は、 | |
* まず先にmvn package等を実行してサポートファイル類を生成しておく必要がある. | |
* (少なくともクラスまたはメソッドのシグネチャを変更追加するたびにmvnでビルドする必要がある。) | |
* その後、IDEから、このメイン関数を呼び出すことができるようになる. | |
* @param args | |
* @throws RunnerException | |
*/ | |
public static void main(String[] args) throws RunnerException { | |
Options opt = new OptionsBuilder() | |
// 実行すべきベンチマークが定義された"クラス名.メソッド名"を正規表現で指定 | |
.include(BufferAccessBenchmark2.class.getSimpleName()) | |
// ウォームアップイテレーション数 "-wi"オプションに相当 | |
.warmupIterations(20) | |
// イテレーション数 "-i"オプションに相当 | |
.measurementIterations(10) | |
// フォーク数 "-f"オプションに相当 | |
.forks(1) | |
// 1回のテストメソッド実行時間 "-r"オプションに相当 | |
.measurementTime(TimeValue.seconds(1)) | |
// 同時実行スレッド数 (1測定毎のスレッド数 (サンプル数が増える)) | |
// .threads(Math.max(1, Runtime.getRuntime().availableProcessors() / 2)) | |
// 測定するモード = スループット | |
//.timeUnit(TimeUnit.MICROSECONDS) | |
//.mode(Mode.SampleTime) | |
.build(); | |
new Runner(opt).run(); | |
} | |
} |
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 jp.seraphyware.jmhexample; | |
import java.lang.reflect.Field; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.nio.DoubleBuffer; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.Level; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.Setup; | |
import org.openjdk.jmh.annotations.State; | |
import org.openjdk.jmh.annotations.TearDown; | |
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.TimeValue; | |
/** | |
* ベンチマーク定義クラス3. | |
* | |
* @author seraphy | |
*/ | |
public class BufferAccessBenchmark3 { | |
/** | |
* テストデータをすべて加算した場合の照合値. | |
*/ | |
private static final double verify = Double.longBitsToDouble(4746793869809549312L); | |
/** | |
* テスト中にスレッドごとベンチマークごとの状態を保持するインスタンス. | |
* | |
* @author seraphy | |
*/ | |
@State(Scope.Thread) | |
protected static class BenchContextBase { | |
/** | |
* バイトオーダー | |
*/ | |
private final ByteOrder byteOrder; | |
/** | |
* ヒープ | |
*/ | |
private byte[] data; | |
/** | |
* ヒープをラップしたバッファ | |
*/ | |
private ByteBuffer bufHeap; | |
/** | |
* ダイレクトバッファ | |
*/ | |
private ByteBuffer bufDirect; | |
/** | |
* アンセーフ | |
*/ | |
@SuppressWarnings("restriction") | |
private sun.misc.Unsafe unsafe; | |
/** | |
* バイトオーダを指定して構築する. | |
* @param byteOrder | |
*/ | |
protected BenchContextBase(ByteOrder byteOrder) { | |
this.byteOrder = byteOrder; | |
} | |
/** | |
* データの初期化. | |
* Trialの場合、スレッドごとベンチマークの開始ごとに一度呼び出される.<br> | |
* (ウォームアップイテレーション、および計測イテレーション中には呼び出されない。) | |
* (Trialがデフォルト、そのほかにIteration, Invocationが指定可能.) | |
*/ | |
@Setup(Level.Trial) | |
public void setup() { | |
// ヒープ上にデータを作成する | |
byte[] data = new byte[512 * 1024]; // 512kb | |
this.data = data; | |
// ヒープ上のByteBufferを作成する. | |
bufHeap = ByteBuffer.wrap(data); | |
bufHeap.order(byteOrder); | |
// ※ テストデータを作成する | |
initData(bufHeap); | |
// byte[] tmp = new byte[8]; | |
// System.arraycopy(data, 0, tmp, 0, tmp.length); | |
// System.out.println("◆" + DatatypeConverter.printHexBinary(tmp)); | |
// ダイレクトメモリを確保してByteBufferを作成する | |
// (データはヒープのものをコピーする) | |
bufDirect = ByteBuffer.allocateDirect(data.length); | |
bufDirect.order(byteOrder); | |
bufDirect.put(data); | |
// アンセーフをリフレクション経由で取得する. | |
initUnsafe(); | |
} | |
/** | |
* アンセーフをリフレクションによって取得する. | |
*/ | |
@SuppressWarnings("restriction") | |
private void initUnsafe() { | |
try { | |
Field field = sun.misc.Unsafe.class | |
.getDeclaredField("theUnsafe"); | |
field.setAccessible(true); | |
unsafe = (sun.misc.Unsafe) field.get(null); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* データを初期化する. | |
* @param buf | |
*/ | |
private void initData(ByteBuffer buf) { | |
DoubleBuffer intBuf = buf.asDoubleBuffer(); | |
double total = 0; | |
for (int idx = 0; idx < data.length / 8; idx++) { | |
intBuf.put((double) idx); | |
total += idx; | |
} | |
//System.out.println("★total=" + Double.doubleToLongBits(total)); | |
if (total != verify) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* スレッドごとベンチマーク終了ごとに呼び出される. | |
*/ | |
@TearDown | |
public void teardown() { | |
} | |
/** | |
* データが格納されているヒープを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public byte[] getData() { | |
return data; | |
} | |
/** | |
* ヒープをラップしているByteBufferを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public ByteBuffer getHeapByteBuffer() { | |
return bufHeap; | |
} | |
/** | |
* ダイレクトバッファを取得する. | |
* バッファは初期化時に一度だけ確保されたものを返す. | |
* @return | |
*/ | |
public ByteBuffer getDirectByteBuffer() { | |
return bufDirect; | |
} | |
/** | |
* アンセーフを取得する. | |
* @return | |
*/ | |
@SuppressWarnings("restriction") | |
public sun.misc.Unsafe getUnsafe() { | |
return unsafe; | |
} | |
} | |
/** | |
* データの並びがLittleEndianのバッファをもつテストデータを作成する. | |
*/ | |
public static class BenchContextLE extends BenchContextBase { | |
public BenchContextLE() { | |
super(ByteOrder.LITTLE_ENDIAN); // Unsafe(intel)にあわせる | |
} | |
} | |
/** | |
* データの並びがBigEndianのバッファをもつテストデータを作成する. | |
*/ | |
public static class BenchContextBE extends BenchContextBase { | |
public BenchContextBE() { | |
super(ByteOrder.BIG_ENDIAN); // JAVA標準にあわせる | |
} | |
} | |
/** | |
* バイトバッファからint値を読み出すテスト | |
* @param buf | |
*/ | |
private static void runByteBuffer(ByteBuffer buf) { | |
buf.rewind(); | |
int limit = buf.limit(); | |
double total = 0; | |
while (buf.position() < limit) { | |
total += buf.getDouble(); | |
} | |
if (total != verify) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* ヒープからUnsafeを使ってint値を読み出すテスト | |
* @param unsafe | |
* @param data | |
*/ | |
@SuppressWarnings("restriction") | |
private static void runUnsafe(sun.misc.Unsafe unsafe, byte[] data) { | |
int offset = sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; | |
int len = data.length + offset; | |
int pos = offset; | |
double total = 0; | |
while (pos < len) { | |
total += unsafe.getDouble(data, (long) pos); | |
pos += 8; | |
} | |
if (total != verify) { | |
throw new RuntimeException("actual=" + total); | |
} | |
} | |
/** | |
* LittleEndianのデータをヒープ上のバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testHeapByteBufferLE(BenchContextLE ctx) { | |
runByteBuffer(ctx.getHeapByteBuffer()); | |
} | |
/** | |
* LittleEndianのデータをダイレクトバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testDirectByteBufferLE(BenchContextLE ctx) { | |
runByteBuffer(ctx.getDirectByteBuffer()); | |
} | |
/** | |
* LittleEndianのデータをアンセーフを使って読み出すベンチマーク | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testUnsafeLE(BenchContextLE ctx) { | |
runUnsafe(ctx.getUnsafe(), ctx.getData()); | |
} | |
/** | |
* BigEndianのデータをヒープ上のバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testHeapByteBufferBE(BenchContextBE ctx) { | |
runByteBuffer(ctx.getHeapByteBuffer()); | |
} | |
/** | |
* BigEndianのデータをダイレクトバイトバッファから読み出すベンチマーク. | |
* @param ctx | |
*/ | |
@Benchmark | |
public void testDirectByteBufferBE(BenchContextBE ctx) { | |
runByteBuffer(ctx.getDirectByteBuffer()); | |
} | |
/** | |
* IDEから実行する場合は、 | |
* まず先にmvn package等を実行してサポートファイル類を生成しておく必要がある. | |
* (少なくともクラスまたはメソッドのシグネチャを変更追加するたびにmvnでビルドする必要がある。) | |
* その後、IDEから、このメイン関数を呼び出すことができるようになる. | |
* @param args | |
* @throws RunnerException | |
*/ | |
public static void main(String[] args) throws RunnerException { | |
Options opt = new OptionsBuilder() | |
// 実行すべきベンチマークが定義された"クラス名.メソッド名"を正規表現で指定 | |
.include(BufferAccessBenchmark3.class.getSimpleName()) | |
// ウォームアップイテレーション数 "-wi"オプションに相当 | |
.warmupIterations(20) | |
// イテレーション数 "-i"オプションに相当 | |
.measurementIterations(10) | |
// フォーク数 "-f"オプションに相当 | |
.forks(1) | |
// 1回のテストメソッド実行時間 "-r"オプションに相当 | |
.measurementTime(TimeValue.seconds(1)) | |
// 同時実行スレッド数 (1測定毎のスレッド数 (サンプル数が増える)) | |
// .threads(Math.max(1, Runtime.getRuntime().availableProcessors() / 2)) | |
// 測定するモード = スループット | |
//.timeUnit(TimeUnit.MICROSECONDS) | |
//.mode(Mode.SampleTime) | |
.build(); | |
new Runner(opt).run(); | |
} | |
} |
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
<!-- Copyright (c) 2014, Oracle America, Inc. All rights reserved. Redistribution | |
and use in source and binary forms, with or without modification, are permitted | |
provided that the following conditions are met: * Redistributions of source | |
code must retain the above copyright notice, this list of conditions and | |
the following disclaimer. * Redistributions in binary form must reproduce | |
the above copyright notice, this list of conditions and the following disclaimer | |
in the documentation and/or other materials provided with the distribution. | |
* Neither the name of Oracle nor the names of its contributors may be used | |
to endorse or promote products derived from this software without specific | |
prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, | |
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY | |
OF SUCH DAMAGE. --> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>jp.seraphyware</groupId> | |
<artifactId>DirectBufferBench</artifactId> | |
<version>0.0.1-SNAPSHOT</version> | |
<packaging>jar</packaging> | |
<name>JMH benchmark: DirectBufferBench</name> | |
<!-- This is the demo/sample template build script for building Java benchmarks | |
with JMH. Edit as needed. --> | |
<prerequisites> | |
<maven>3.0</maven> | |
</prerequisites> | |
<dependencies> | |
<dependency> | |
<groupId>org.openjdk.jmh</groupId> | |
<artifactId>jmh-core</artifactId> | |
<version>${jmh.version}</version> | |
</dependency> | |
<dependency> | |
<groupId>org.openjdk.jmh</groupId> | |
<artifactId>jmh-generator-annprocess</artifactId> | |
<version>${jmh.version}</version> | |
<scope>provided</scope> | |
</dependency> | |
</dependencies> | |
<properties> | |
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
<jmh.version>1.11.2</jmh.version> | |
<javac.target>1.8</javac.target> | |
<uberjar.name>benchmarks</uberjar.name> | |
</properties> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-compiler-plugin</artifactId> | |
<version>3.1</version> | |
<configuration> | |
<compilerVersion>${javac.target}</compilerVersion> | |
<source>${javac.target}</source> | |
<target>${javac.target}</target> | |
</configuration> | |
</plugin> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-shade-plugin</artifactId> | |
<version>2.2</version> | |
<executions> | |
<execution> | |
<phase>package</phase> | |
<goals> | |
<goal>shade</goal> | |
</goals> | |
<configuration> | |
<finalName>${uberjar.name}</finalName> | |
<transformers> | |
<transformer | |
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> | |
<mainClass>org.openjdk.jmh.Main</mainClass> | |
</transformer> | |
</transformers> | |
<filters> | |
<filter> | |
<!-- Shading signed JARs will fail without this. http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar --> | |
<artifact>*:*</artifact> | |
<excludes> | |
<exclude>META-INF/*.SF</exclude> | |
<exclude>META-INF/*.DSA</exclude> | |
<exclude>META-INF/*.RSA</exclude> | |
</excludes> | |
</filter> | |
</filters> | |
</configuration> | |
</execution> | |
</executions> | |
</plugin> | |
</plugins> | |
<pluginManagement> | |
<plugins> | |
<plugin> | |
<artifactId>maven-clean-plugin</artifactId> | |
<version>2.5</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-deploy-plugin</artifactId> | |
<version>2.8.1</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-install-plugin</artifactId> | |
<version>2.5.1</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-jar-plugin</artifactId> | |
<version>2.4</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-javadoc-plugin</artifactId> | |
<version>2.9.1</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-resources-plugin</artifactId> | |
<version>2.6</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-site-plugin</artifactId> | |
<version>3.3</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-source-plugin</artifactId> | |
<version>2.2.1</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-surefire-plugin</artifactId> | |
<version>2.17</version> | |
</plugin> | |
</plugins> | |
</pluginManagement> | |
</build> | |
</project> |
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
# JMH 1.11.2 (released 16 days ago) | |
# VM version: JDK 1.8.0_60, VM 25.60-b23 | |
# VM invoker: C:\Java\jdk1.8.0_60\jre\bin\java.exe | |
# VM options: -Dfile.encoding=UTF-8 | |
# Warmup: 20 iterations, 1 s each | |
# Measurement: 10 iterations, 1 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Throughput, ops/time | |
# Benchmark: jp.seraphyware.jmhexample.BufferAccessBenchmark.testDirectByteBufferBE | |
Result "testDirectByteBufferBE": | |
14749.779 ±(99.9%) 54.380 ops/s [Average] | |
(min, avg, max) = (14690.298, 14749.779, 14806.503), stdev = 35.969 | |
CI (99.9%): [14695.400, 14804.159] (assumes normal distribution) | |
Result "testDirectByteBufferLE": | |
21970.174 ±(99.9%) 154.358 ops/s [Average] | |
(min, avg, max) = (21833.488, 21970.174, 22122.518), stdev = 102.098 | |
CI (99.9%): [21815.816, 22124.532] (assumes normal distribution) | |
Result "testHeapByteArray": | |
4744.254 ±(99.9%) 83.476 ops/s [Average] | |
(min, avg, max) = (4618.953, 4744.254, 4799.570), stdev = 55.214 | |
CI (99.9%): [4660.778, 4827.730] (assumes normal distribution) | |
Result "testHeapByteBufferBE": | |
4518.875 ±(99.9%) 491.083 ops/s [Average] | |
(min, avg, max) = (4124.723, 4518.875, 4919.513), stdev = 324.821 | |
CI (99.9%): [4027.792, 5009.958] (assumes normal distribution) | |
Result "testHeapByteBufferLE": | |
4581.578 ±(99.9%) 618.657 ops/s [Average] | |
(min, avg, max) = (4104.452, 4581.578, 4948.241), stdev = 409.203 | |
CI (99.9%): [3962.921, 5200.234] (assumes normal distribution) | |
Result "testUnsafeLE": | |
21981.865 ±(99.9%) 125.801 ops/s [Average] | |
(min, avg, max) = (21841.979, 21981.865, 22068.251), stdev = 83.209 | |
CI (99.9%): [21856.064, 22107.665] (assumes normal distribution) | |
# Run complete. Total time: 00:03:02 | |
Benchmark Mode Cnt Score Error Units | |
BufferAccessBenchmark.testDirectByteBufferBE thrpt 10 14749.779 ± 54.380 ops/s | |
BufferAccessBenchmark.testDirectByteBufferLE thrpt 10 21970.174 ± 154.358 ops/s | |
BufferAccessBenchmark.testHeapByteArray thrpt 10 4744.254 ± 83.476 ops/s | |
BufferAccessBenchmark.testHeapByteBufferBE thrpt 10 4518.875 ± 491.083 ops/s | |
BufferAccessBenchmark.testHeapByteBufferLE thrpt 10 4581.578 ± 618.657 ops/s | |
BufferAccessBenchmark.testUnsafeLE thrpt 10 21981.865 ± 125.801 ops/s |
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
# JMH 1.11.2 (released 16 days ago) | |
# VM version: JDK 1.8.0_60, VM 25.60-b23 | |
# VM invoker: C:\Java\jdk1.8.0_60\jre\bin\java.exe | |
# VM options: -Dfile.encoding=UTF-8 | |
# Warmup: 20 iterations, 1 s each | |
# Measurement: 10 iterations, 1 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Sampling time | |
# Benchmark: jp.seraphyware.jmhexample.BufferAccessBenchmark.testDirectByteBufferBE | |
Iteration 1: n = 14259, mean = 70 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 68, 73, 85, 129, 164, 180, 181 us/op | |
Iteration 2: n = 14022, mean = 71 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 68, 76, 87, 138, 176, 377, 485 us/op | |
Iteration 3: n = 14341, mean = 70 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 67, 70, 84, 135, 175, 342, 390 us/op | |
Iteration 4: n = 14122, mean = 71 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 68, 76, 87, 137, 172, 241, 241 us/op | |
Iteration 5: n = 14138, mean = 71 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 68, 76, 87, 139, 165, 198, 205 us/op | |
Iteration 6: n = 14624, mean = 68 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 66, 69, 77, 103, 145, 181, 184 us/op | |
Iteration 7: n = 14589, mean = 68 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 66, 69, 78, 103, 153, 173, 174 us/op | |
Iteration 8: n = 14578, mean = 69 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 66, 69, 78, 107, 148, 163, 164 us/op | |
Iteration 9: n = 14606, mean = 68 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 66, 69, 76, 105, 147, 165, 169 us/op | |
Iteration 10: n = 14259, mean = 70 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 66, 68, 75, 85, 121, 155, 207, 233 us/op | |
Result "testDirectByteBufferBE": | |
69.583 ±(99.9%) 0.088 us/op [Average] | |
(min, avg, max) = (65.664, 69.583, 484.864), stdev = 10.159 | |
CI (99.9%): [69.495, 69.672] (assumes normal distribution) | |
Samples, N = 143538 | |
mean = 69.583 ±(99.9%) 0.088 us/op | |
min = 65.664 us/op | |
p( 0.0000) = 65.664 us/op | |
p(50.0000) = 67.712 us/op | |
p(90.0000) = 70.912 us/op | |
p(95.0000) = 83.840 us/op | |
p(99.0000) = 126.492 us/op | |
p(99.9000) = 162.304 us/op | |
p(99.9900) = 207.104 us/op | |
p(99.9990) = 443.401 us/op | |
p(99.9999) = 484.864 us/op | |
max = 484.864 us/op | |
Iteration 1: n = 10857, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 53, 88, 108, 149, 149 us/op | |
Iteration 2: n = 10619, mean = 47 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 45, 47, 55, 97, 117, 150, 151 us/op | |
Iteration 3: n = 10738, mean = 47 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 55, 90, 110, 142, 143 us/op | |
Iteration 4: n = 10942, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 47, 72, 106, 133, 133 us/op | |
Iteration 5: n = 10874, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 53, 73, 105, 136, 136 us/op | |
Iteration 6: n = 10878, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 53, 74, 106, 119, 119 us/op | |
Iteration 7: n = 10955, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 48, 71, 106, 107, 107 us/op | |
Iteration 8: n = 10945, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 47, 71, 106, 107, 108 us/op | |
Iteration 9: n = 10842, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 54, 86, 110, 172, 174 us/op | |
Iteration 10: n = 10852, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 53, 86, 111, 122, 122 us/op | |
Result "testDirectByteBufferLE": | |
46.035 ±(99.9%) 0.064 us/op [Average] | |
(min, avg, max) = (43.968, 46.035, 174.336), stdev = 6.423 | |
CI (99.9%): [45.971, 46.099] (assumes normal distribution) | |
Samples, N = 108502 | |
mean = 46.035 ±(99.9%) 0.064 us/op | |
min = 43.968 us/op | |
p( 0.0000) = 43.968 us/op | |
p(50.0000) = 44.224 us/op | |
p(90.0000) = 46.592 us/op | |
p(95.0000) = 53.312 us/op | |
p(99.0000) = 81.408 us/op | |
p(99.9000) = 107.520 us/op | |
p(99.9900) = 131.635 us/op | |
p(99.9990) = 172.333 us/op | |
p(99.9999) = 174.336 us/op | |
max = 174.336 us/op | |
Iteration 1: n = 6413, mean = 156 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 162, 169, 220, 326, 342, 342 us/op | |
Iteration 2: n = 6407, mean = 156 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 161, 170, 240, 321, 344, 344 us/op | |
Iteration 3: n = 6409, mean = 156 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 159, 169, 288, 343, 444, 444 us/op | |
Iteration 4: n = 6436, mean = 155 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 162, 169, 218, 313, 354, 354 us/op | |
Iteration 5: n = 6473, mean = 154 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 158, 165, 216, 333, 413, 413 us/op | |
Iteration 6: n = 6445, mean = 155 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 159, 168, 220, 317, 344, 344 us/op | |
Iteration 7: n = 6462, mean = 155 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 159, 168, 209, 322, 360, 360 us/op | |
Iteration 8: n = 6460, mean = 155 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 159, 168, 214, 316, 334, 334 us/op | |
Iteration 9: n = 6473, mean = 154 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 159, 168, 220, 319, 352, 352 us/op | |
Iteration 10: n = 6440, mean = 155 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 150, 151, 160, 168, 220, 325, 344, 344 us/op | |
Result "testHeapByteArray": | |
155.058 ±(99.9%) 0.194 us/op [Average] | |
(min, avg, max) = (149.504, 155.058, 444.416), stdev = 14.943 | |
CI (99.9%): [154.864, 155.251] (assumes normal distribution) | |
Samples, N = 64418 | |
mean = 155.058 ±(99.9%) 0.194 us/op | |
min = 149.504 us/op | |
p( 0.0000) = 149.504 us/op | |
p(50.0000) = 150.528 us/op | |
p(90.0000) = 159.488 us/op | |
p(95.0000) = 168.448 us/op | |
p(99.0000) = 227.072 us/op | |
p(99.9000) = 325.632 us/op | |
p(99.9900) = 357.947 us/op | |
p(99.9990) = 444.416 us/op | |
p(99.9999) = 444.416 us/op | |
max = 444.416 us/op | |
Iteration 1: n = 4607, mean = 217 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 212, 226, 243, 359, 433, 477, 477 us/op | |
Iteration 2: n = 4666, mean = 214 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 221, 233, 330, 454, 470, 470 us/op | |
Iteration 3: n = 4706, mean = 212 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 219, 227, 311, 423, 442, 442 us/op | |
Iteration 4: n = 4708, mean = 212 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 218, 227, 306, 418, 498, 498 us/op | |
Iteration 5: n = 4697, mean = 213 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 225, 228, 289, 444, 565, 565 us/op | |
Iteration 6: n = 4701, mean = 213 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 218, 227, 314, 460, 479, 479 us/op | |
Iteration 7: n = 4707, mean = 212 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 219, 226, 295, 397, 446, 446 us/op | |
Iteration 8: n = 4703, mean = 212 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 219, 227, 307, 436, 467, 467 us/op | |
Iteration 9: n = 4695, mean = 213 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 207, 225, 226, 339, 454, 461, 461 us/op | |
Iteration 10: n = 4608, mean = 217 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 207, 212, 225, 243, 362, 464, 481, 481 us/op | |
Result "testHeapByteBufferBE": | |
213.519 ±(99.9%) 0.304 us/op [Average] | |
(min, avg, max) = (206.848, 213.519, 565.248), stdev = 19.993 | |
CI (99.9%): [213.215, 213.823] (assumes normal distribution) | |
Samples, N = 46798 | |
mean = 213.519 ±(99.9%) 0.304 us/op | |
min = 206.848 us/op | |
p( 0.0000) = 206.848 us/op | |
p(50.0000) = 207.360 us/op | |
p(90.0000) = 220.672 us/op | |
p(95.0000) = 229.888 us/op | |
p(99.0000) = 323.072 us/op | |
p(99.9000) = 437.760 us/op | |
p(99.9900) = 479.888 us/op | |
p(99.9990) = 565.248 us/op | |
p(99.9999) = 565.248 us/op | |
max = 565.248 us/op | |
Iteration 1: n = 5174, mean = 193 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 200, 207, 261, 382, 426, 426 us/op | |
Iteration 2: n = 5205, mean = 192 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 197, 203, 260, 398, 419, 419 us/op | |
Iteration 3: n = 5196, mean = 192 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 197, 203, 262, 392, 408, 408 us/op | |
Iteration 4: n = 5180, mean = 193 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 201, 207, 268, 381, 398, 398 us/op | |
Iteration 5: n = 5196, mean = 192 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 197, 206, 259, 399, 514, 514 us/op | |
Iteration 6: n = 5183, mean = 193 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 199, 206, 263, 389, 414, 414 us/op | |
Iteration 7: n = 5169, mean = 193 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 201, 207, 261, 390, 429, 429 us/op | |
Iteration 8: n = 5185, mean = 193 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 199, 207, 252, 395, 426, 426 us/op | |
Iteration 9: n = 5186, mean = 193 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 199, 206, 253, 360, 392, 392 us/op | |
Iteration 10: n = 5177, mean = 193 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 188, 188, 200, 207, 257, 398, 435, 435 us/op | |
Result "testHeapByteBufferLE": | |
192.723 ±(99.9%) 0.216 us/op [Average] | |
(min, avg, max) = (187.904, 192.723, 513.536), stdev = 14.930 | |
CI (99.9%): [192.508, 192.939] (assumes normal distribution) | |
Samples, N = 51851 | |
mean = 192.723 ±(99.9%) 0.216 us/op | |
min = 187.904 us/op | |
p( 0.0000) = 187.904 us/op | |
p(50.0000) = 188.416 us/op | |
p(90.0000) = 198.656 us/op | |
p(95.0000) = 206.592 us/op | |
p(99.0000) = 259.328 us/op | |
p(99.9000) = 389.632 us/op | |
p(99.9900) = 424.656 us/op | |
p(99.9990) = 513.536 us/op | |
p(99.9999) = 513.536 us/op | |
max = 513.536 us/op | |
Iteration 1: n = 11004, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 45, 47, 70, 98, 107, 107 us/op | |
Iteration 2: n = 11028, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 45, 47, 69, 106, 146, 148 us/op | |
Iteration 3: n = 11026, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 46, 47, 65, 105, 114, 115 us/op | |
Iteration 4: n = 11000, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 45, 47, 71, 106, 114, 115 us/op | |
Iteration 5: n = 11001, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 45, 47, 72, 106, 156, 158 us/op | |
Iteration 6: n = 11084, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 45, 47, 63, 106, 114, 115 us/op | |
Iteration 7: n = 10998, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 46, 47, 71, 100, 131, 133 us/op | |
Iteration 8: n = 11009, mean = 45 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 45, 47, 71, 105, 106, 106 us/op | |
Iteration 9: n = 10933, mean = 46 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 44, 47, 47, 73, 106, 117, 117 us/op | |
Iteration 10: n = 10578, mean = 47 us/op, p{0.00, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00} = 44, 45, 47, 63, 88, 116, 145, 146 us/op | |
Result "testUnsafeLE": | |
45.545 ±(99.9%) 0.053 us/op [Average] | |
(min, avg, max) = (43.968, 45.545, 157.696), stdev = 5.347 | |
CI (99.9%): [45.492, 45.598] (assumes normal distribution) | |
Samples, N = 109661 | |
mean = 45.545 ±(99.9%) 0.053 us/op | |
min = 43.968 us/op | |
p( 0.0000) = 43.968 us/op | |
p(50.0000) = 44.224 us/op | |
p(90.0000) = 46.592 us/op | |
p(95.0000) = 46.912 us/op | |
p(99.0000) = 72.064 us/op | |
p(99.9000) = 105.856 us/op | |
p(99.9900) = 124.071 us/op | |
p(99.9990) = 156.756 us/op | |
p(99.9999) = 157.696 us/op | |
max = 157.696 us/op | |
# Run complete. Total time: 00:03:02 | |
Benchmark Mode Cnt Score Error Units | |
BufferAccessBenchmark.testDirectByteBufferBE sample 143538 69.583 ± 0.088 us/op | |
BufferAccessBenchmark.testDirectByteBufferLE sample 108502 46.035 ± 0.064 us/op | |
BufferAccessBenchmark.testHeapByteArray sample 64418 155.058 ± 0.194 us/op | |
BufferAccessBenchmark.testHeapByteBufferBE sample 46798 213.519 ± 0.304 us/op | |
BufferAccessBenchmark.testHeapByteBufferLE sample 51851 192.723 ± 0.216 us/op | |
BufferAccessBenchmark.testUnsafeLE sample 109661 45.545 ± 0.053 us/op |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment