jjzjj

Java I/O 与 NIO : Quick Benchmark Comparison

coder 2024-03-20 原文

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

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

注意:这是使用 JDK 7

结果(3 次试验):

平均 I/O 传输 21789.3 毫秒

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 位架构

最佳答案

建议

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

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

关于Java I/O 与 NIO : Quick Benchmark Comparison,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9152018/

有关Java I/O 与 NIO : Quick Benchmark Comparison的更多相关文章

  1. ruby-on-rails - 安装 nio4r 时出错 - 2

    请帮帮我。我尝试安装gemnio4r,但此日志有错误:ERROR:Errorinstallingnio4r:ERROR:Failedtobuildgemnativeextension.currentdirectory:/var/lib/gems/2.3.0/gems/nio4r-1.2.1/ext/nio4r/usr/bin/ruby2.3-r./siteconf20161020-13985-1c6zxok.rbextconf.rbmkmf.rbcan'tfindheaderfilesforrubyat/usr/lib/ruby/include/ruby.hextconffailed,

  2. ruby-on-rails - 如何在 Rails 5.0.0 上修复 bundle 安装 "nio4r error" - 2

    准确的错误是:Anerroroccurredwhileinstallingnio4r(1.2.1),andbundlercannotcontinue.Makesurethat'geminstallnio4r-v'1.2.1''succeedsbeforebundling.这是一条轨迹:Fetchinggemmetadatafromhttps://rubygems.org/Fetchingversionmetadatafromhttps://rubygems.org/Fetchingdependencymetadatafromhttps://rubygems.org/Usingrake1

  3. ruby-on-rails - 安装 "nio4r": Failed to build gem native extension 时的 rails 5.0.0 - 2

    这是日志:http://pastebin.com/CAgur9xdInstallingnio4r1.2.1withnativeextensionsGem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension.C:/RailsInstaller/Ruby2.2.0/bin/ruby.exe-r./siteconf20160720-8272-c88sgk.rbextconf.rb--with-cflags=-std=c99checkingforunistd.h...***extconf.rbfailed***Couldnotcreat

  4. ruby-on-rails - bundle 安装 : ERROR: Failed to build gem native extension. nio4r gem - 2

    我目前正在使用以下项目进行项目:rvm1.26.11ruby2.2.1p85我尝试运行bundleinstall但不断收到以下错误:Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension.并且,以下:Anerroroccurredwhileinstallingnio4r(1.0.0),andBundlercannotcontinue.Makesurethat`geminstallnio4r-v'1.0.0'`succeedsbeforebundling.当我尝试运行geminstallnio4r-v'1.0.0'时:Buil

  5. xml - java.nio.charset.UnmappableCharacterException : Input length = 1 - 2

    完整错误信息:java.nio.charset.UnmappableCharacterException:Inputlength=1atjava.nio.charset.CoderResult.throwException(CoderResult.java:261)atsun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:266)atsun.nio.cs.StreamEncoder.write(StreamEncoder.java:106)atsun.nio.cs.StreamEncoder.write(StreamEncoder.

  6. Java nio 监视服务 : Watch Windows drives list - 2

    我想在连接USB驱动器时收到通知。所以java说:“驱动器H:已创建”。有没有办法用WatchService做到这一点?看根目录是行不通的。它只监视当前驱动器的根目录:Paths.get("/").register 最佳答案 您不能使用WatchService来做到这一点。由于您只担心Windows,您可以简单地轮询FileSystem.getRootDirectories并检测变化。try{Listroots=asList(FileSystems.getDefault().getRootDirectories());for(;;)

  7. Java 7 NIO/JPathWatch 问题 - 在 Windows 中移动目录 - 2

    我已经实现了一个应用程序,它使用JavaNIO的WatchService来监视目录树中文件和文件夹的更改。在WindowsXP上运行时,所有文件系统更改都会被拾取-除了通过在资源管理器中拖放将目录移动到受监视的树中。选取事件以剪切和粘贴目录(ctrl+x、ctrl+v),而不是拖放(编辑-请参阅下面的更新)。我已经使用JPathWatch重新实现了解决方案,但是这也存在同样的问题。我正在注册标准的ENTRY_CREATE、ENTRY_DELETE和ENTRY_MODIFY并且我还使用了好奇的、文档不足的com.sun.nio.file.ExtendedWatchEventModifie

  8. java - 在 java 中移动目录会抛出 java.nio.file.FileAlreadyExistsException - 2

    我正在创建一个回滚功能,这是我想要实现的:在与data文件夹相同的位置创建一个tmp文件夹;在执行任何操作之前,我将所有内容从data文件夹复制到tmp文件夹(少量数据)。回滚时我想删除数据文件夹并将重命名tmp文件夹到数据文件夹.这是我试过的StringcontentPath="c:\\temp\\data";StringtmpContentPath="c:\\temp\\data.TMP";if(Files.exists(Paths.get(tmpContentPath))&&Files.list(Paths.get(tmpContentPath)).count()>0){File

  9. 关于springboot访问tomcat,线程http-nio-8080-exec的来源问题 - 2

    最近在看并发操作时候,例如jmeter进行接口压测(本地自己的springboot2的环境),发现一个有趣的现象,就是关于线程http-nio-8080-exec-1,http-nio-8080-exec-2等等的出现。但是这个线程数不管我的压测数是多少这个线程数不会超过10.抱着好奇的心去搜索了一下相关的文章,但是没有看到比较合适的。然后就只有自己去跟了一下源码。在此自己总结一下。两个问题:1、这个http-nio-8080-exec东西是怎么来的2、为什么这个线程数不超过10把这两个问题其实可以一起归为一个问题来跟代码进行解决:因为我们知道,一般在自定义线程或者线程池名称的时候,我们是可以

  10. java - (Java 7 NIO.2) 监视服务线程的自定义名称 - 2

    在Java7中使用nio.2,当您创建这样的watch服务时:WatchServicewatcher=FileSystems.getDefault().newWatchService();然后,启动后台线程,在无限循环中轮询文件系统事件。此线程的名称是“Thread-n”,这在调查线程转储或分析session期间有点麻烦。我们可以更改该线程的名称吗? 最佳答案 直接看实现,好像不行。如果您不介意一些小技巧,您可以找到线程并重命名它。类似于(//TODO:进行错误检查)SetthreadsBefore=Thread.getAllSta

随机推荐