基于JMH对Java NIO 零拷贝进行基准测试

背景

Java NIO中引入了零拷贝的API,本文测试零拷贝与传统IO的性能差异,通过借助基准测试工具JMH进行测试

测试用例

简单些了一个JMH的实例,迭代100次,计算每次的平均时间

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 java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

/**
 * 通过复制文件来测试 传统IO VS 零拷贝 的性能
 */
@Warmup(iterations = 1) // 预热迭代次数
@Measurement(iterations = 100)  // 测试迭代测试,作为计算的依据
@Fork(1) // 模拟1个线程处理
@BenchmarkMode(Mode.SingleShotTime) // 每次迭代执行一次的时间
public class ZeroCopyTest {

    /**
     * 基准测试用例,测试零拷贝性能
     * @throws IOException
     */
    @Benchmark
    public void testWithZeroCopy() throws IOException {
        FileInputStream inputStream = new FileInputStream("D:\\soft\\YNote.exe");
        File outFile = new File("pdi.zip");
        FileOutputStream outputStream = new FileOutputStream(outFile, false);
        FileChannel inputChannel = inputStream.getChannel();
        FileChannel outChannel = outputStream.getChannel();
        outChannel.position(0);
        inputChannel.transferTo(0, inputChannel.size(), outChannel);
        inputStream.close();
        outputStream.close();
    }

    /**
     * 基准测试用例,测试传统IO性能
     * @throws IOException
     */
    @Benchmark
    public void testWithoutZeroCopy() throws IOException {
        FileInputStream inputStream = new FileInputStream("D:\\soft\\YNote.exe");
        File outFile = new File("pdi.zip");
        FileOutputStream outputStream = new FileOutputStream(outFile, false);
        byte[] buffer = new byte[4086];
        while (true) {
            int length = inputStream.read(buffer);
            if (length < 0) {
                break;
            }
            outputStream.write(buffer, 0, length);
        }
        outputStream.flush();
        inputStream.close();
        outputStream.close();
    }

    /**
     * 通过main方法的方式启动JMH测试,也可以通过命令启动,具体方法可使用搜索引擎查询
     * @param args
     * @throws RunnerException
     * @throws IOException
     */
    public static void main(String[] args) throws RunnerException, IOException {
        Options opt = new OptionsBuilder()
                .include(ZeroCopyTest.class.getSimpleName())
                .build();
        new Runner(opt).run();
    }

}

结果分析

由于每个用例执行了100次,具体的每次的执行时间就不做输出,下面是统计结果部分

Benchmark                         Mode  Cnt  Score           Error  Units
ZeroCopyTest.testWithZeroCopy       ss  100  0.051 ± 0.004          s/op
ZeroCopyTest.testWithoutZeroCopy    ss  100  0.170 ± 0.006          s/op

从统计结果看,使用零拷贝的效率,大概是传统IO的3倍多。

你可能感兴趣的:(java)