【问题标题】:Java I/O vs NIO: Quick Benchmark ComparisonJava I/O 与 NIO:快速基准比较
【发布时间】:2012-02-05 18:56:33
【问题描述】:

我最近读到,由于多核机器的新可用性,Java 的 I/O 性能在较新的计算机中优于 NIO。

我使用 localhost 环回地址运行了一个快速测试,比较了 LAN 上 I/O 和 NIO 的传输时间。

注意:这里使用的是 JDK 7

结果(3次试验):

平均 I/O 传输 21789.3ms

NIO 传输平均 22771.0ms

还值得注意的是,与 I/O 相比,每次 NIO 传输的 CPU 使用率似乎高出约 10%。

我的问题是我的比较代码是否公平?我是否编写了良好/相等的 I/O 和 NIO 代码?如果没有,我该如何改进并重新运行此测试?

    public static void main(String[] args) {
    System.out.println("Initiating test sequence...");
    new Thread(new Client()).start();
    try {
        System.out.println("Server I/O initiating...");
        ServerSocket server = new ServerSocket(5555);
        Socket sock = server.accept();
        System.out.println("Server connected to client successfully");
        InputStream is = sock.getInputStream();
        File output = new File("C:/test_root/video.avi");
        FileOutputStream fos = new FileOutputStream(output);
        byte[] data = new byte[1024];
        int len=0;
        System.out.println("Server initiating transfer - Timer starting");
        long start = System.currentTimeMillis();
        while((len=is.read(data))>0) {
            fos.write(data, 0, len);
            fos.flush();
        }
        fos.close();
        is.close();
        sock.close();
        server.close();
        long end = System.currentTimeMillis();
        System.out.println("Network I/O transfer time = "+(end-start)+"ms");

        System.out.println("Server NIO initiating...");
        ServerSocketChannel serverChan = ServerSocketChannel.open();
        serverChan.bind(new InetSocketAddress(5555));
        SocketChannel chan = serverChan.accept();
        chan.configureBlocking(false);
        System.out.println("Server channel connected");
        FileChannel fc = (FileChannel) Files.newByteChannel(Paths.get("C:/test_root/video.avi"), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
        ByteBuffer buff = ByteBuffer.allocate(1024);
        System.out.println("Server initiating transfer - Timer starting");
        start = System.currentTimeMillis();
        while(chan.read(buff)>=0 || buff.position() > 0) {
            buff.flip();
            fc.write(buff);
            buff.compact();
        }
        chan.close();
        fc.close();
        serverChan.close();
        end = System.currentTimeMillis();
        System.out.println("Network NIO transfer time = "+(end-start)+"ms");
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println("Test completed!");
}

static class Client implements Runnable {

    public void run() {
        try {
            System.out.println("Client I/O initiating...");
            Socket sock = new Socket("localhost", 5555);
            System.out.println("Client connected to server successfully!");
            OutputStream os = sock.getOutputStream();
            File input = new File(System.getProperty("user.home")+"/Documents/clip0025.avi");
            FileInputStream fis = new FileInputStream(input);
            byte[] data = new byte[1024];
            int len=0;
            int tot=0;
            int perc=0;
            while((len=fis.read(data))>0) {
                os.write(data, 0, len);
                os.flush();
                tot+=len;
                int prev = perc;
                perc = getPercentage(tot, input.length());
                if(perc !=prev && (perc == 10 || perc == 25 || perc == 50 || perc == 75 || perc == 98))
                    System.out.println("Client reporting: "+perc+"% read");
            }
            os.close();
            fis.close();
            sock.close();

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Client NIO initiating...");
            SocketChannel sc = SocketChannel.open();
            boolean connected = sc.connect(new InetSocketAddress("localhost",5555));
            if(!connected)
                connected = sc.finishConnect();
            if(!connected)
                throw(new IOException("Client failed to connect"));
            System.out.println("Client channel connected");
            sc.configureBlocking(false);
            FileChannel fc = (FileChannel) Files.newByteChannel(input.toPath(), StandardOpenOption.READ);
            ByteBuffer buff = ByteBuffer.allocate(1024);
            len=0;
            tot=0;
            while((len=fc.read(buff))>=0||buff.position()>0) {
                buff.flip();
                sc.write(buff);
                buff.compact();
                tot+=len;
                int prev = perc;
                perc = getPercentage(tot, input.length());
                if(perc !=prev && (perc == 10 || perc == 25 || perc == 50 || perc == 75 || perc == 98))
                    System.out.println("Client reporting: "+perc+"% read");
            }
            sc.close();
            fc.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

附加信息:

Dell Studio XPS 435MT 上的 Windows Vista (SP2)

第一代 i7 四核处理器 2.67GHz

6GB 内存

64 位架构

【问题讨论】:

  • 我不相信基准测试部分是公平的——在 Java 中,你确实需要做一些事情,比如预热 JVM 等等。您也许可以使用像 code.google.com/p/caliper 这样的基准测试工具。
  • @LouisWasserman 您如何建议预热 JVM 和/或改进此代码?
  • 使用由知道自己在 JVM 上做什么的人构建的基准测试框架,本质上。不要编写自己的“定时操作”代码。错误的方法比正确的方法多得多。
  • 您同时处理多少个连接? Java NIO 的主要设计目的是避免“每个客户端一个线程”的方法。人们会认为真正的 NIO 基准测试将涉及大量客户端冲击同一个服务器实例。
  • NIO 的重点是解决传统 IO 的可扩展性问题,当尝试 5k 多个客户端时。这个基准完全没有意义。

标签: java networking io benchmarking nio


【解决方案1】:

建议

  • 尝试比较阻塞 IO 和阻塞 NIO。你的代码会更短。如果要测试 IO,请在客户端和服务器上使用 IO。如果您要使用 NIO,请在两端使用相同的。
  • 使用直接 ByteBuffers。
  • 不要读/写文件,因为它们不是基准测试的一部分,而且速度可能会慢得多。只需传递空白数据块即可。
  • 尝试不同的块大小,例如8 KB。
  • 考虑要交换的数据类型。例如ByteBuffer 可以提高读取intlong 的效率。
  • 报告带宽方面的数字。我希望在环回上看到 1-3 GB/秒。

http://vanillajava.blogspot.com/2010/07/java-nio-is-faster-than-java-io-for.html

【讨论】:

  • 你可能会觉得这个链接很有趣。
  • 您是否建议使用两个独立的 JVM 来测试 I/O 与 NIO 并分别进行预热?
  • 要分离“主”类,在不同时间运行相同的热身量。即对您的应用程序来说什么是现实的。
猜你喜欢
  • 2011-05-02
  • 2012-01-20
  • 2017-09-20
  • 2021-08-17
  • 2016-08-12
  • 2015-07-05
  • 1970-01-01
  • 2017-03-26
  • 2017-01-14
相关资源
最近更新 更多