要allocate()或者allocateDirect(),这是一个问题.
多年以来我一直坚持认为,因为DirectByteBuffers是OS级别的直接内存映射,所以get/put调用的执行速度比HeapByteBuffers 快.到目前为止,我从未真正有兴趣了解有关情况的具体细节.我想知道两种类型的ByteBuffer哪种更快,哪种条件更快.
我工作的一些SocketChannel至- SocketChannel代码会做最好用直接字节缓冲区- (几十到几百每个连接的兆字节),长寿命,大而散列出具有确切循环结构FileChannelS,我跑了一些微在基准测试ByteBuffer.allocate()与ByteBuffer.allocateDirect()性能.
结果出人意料,我无法解释.在下图中,对于ByteBuffer.allocate()传输实现,在256KB和512KB处有一个非常明显的悬崖- 性能下降了~50%!这似乎也是一个较小的性能悬崖ByteBuffer.allocateDirect().(%-gain系列有助于可视化这些变化.)
缓冲区大小(字节)与时间(MS)

为什么奇数性能曲线ByteBuffer.allocate()与ByteBuffer.allocateDirect()?之间存在差异? 幕后究竟发生了什么?
它很可能取决于硬件和操作系统,所以这里有以下细节:
源代码,按要求:
package ch.dietpizza.bench;
import static java.lang.String.format;
import static java.lang.System.out;
import static java.nio.ByteBuffer.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class SocketChannelByteBufferExample {
private static WritableByteChannel target;
private static ReadableByteChannel source; …Run Code Online (Sandbox Code Playgroud) 我想比较直接字节缓冲区(java.nio.ByteBuffer,堆外)和堆缓冲区(通过数组实现)的读取和写入性能。我的理解是,ByteBuffer 在堆外比堆缓冲区至少有两个好处。首先,它不会被 GC 考虑,其次(我希望我做对了)JVM 在读取和写入它时不会使用中间/临时缓冲区。这些优点可能使堆外缓冲区比堆缓冲区更快。如果这是正确的,我不应该期望我的基准显示相同吗?它总是比非堆缓冲区更快地显示堆缓冲区。
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(value = 2, jvmArgs = {"-Xms2G", "-Xmx4G"})
@Warmup(iterations = 3)
@Measurement(iterations = 10)
public class BasicTest {
@Param({"100000"})
private int N;
final int bufferSize = 10000;
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(8 * bufferSize);
long buffer[] = new long[bufferSize];
public static void main(String arep[]) throws Exception {
Options opt = new OptionsBuilder()
.include(BasicTest.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
@Benchmark
public void offHeapBuffer(Blackhole blackhole) {
IntStream.range(0, bufferSize).forEach(index -> {
byteBuffer.putLong(index, 500 * index);
blackhole.consume(byteBuffer.get(index));
}); …Run Code Online (Sandbox Code Playgroud)