我最近读到,由于多核计算机的新可用性,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 位架构
最佳答案
建议
int 和 long 更有效率。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/
请帮帮我。我尝试安装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,
准确的错误是:Anerroroccurredwhileinstallingnio4r(1.2.1),andbundlercannotcontinue.Makesurethat'geminstallnio4r-v'1.2.1''succeedsbeforebundling.这是一条轨迹:Fetchinggemmetadatafromhttps://rubygems.org/Fetchingversionmetadatafromhttps://rubygems.org/Fetchingdependencymetadatafromhttps://rubygems.org/Usingrake1
这是日志: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
我目前正在使用以下项目进行项目: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
完整错误信息: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.
我想在连接USB驱动器时收到通知。所以java说:“驱动器H:已创建”。有没有办法用WatchService做到这一点?看根目录是行不通的。它只监视当前驱动器的根目录:Paths.get("/").register 最佳答案 您不能使用WatchService来做到这一点。由于您只担心Windows,您可以简单地轮询FileSystem.getRootDirectories并检测变化。try{Listroots=asList(FileSystems.getDefault().getRootDirectories());for(;;)
我已经实现了一个应用程序,它使用JavaNIO的WatchService来监视目录树中文件和文件夹的更改。在WindowsXP上运行时,所有文件系统更改都会被拾取-除了通过在资源管理器中拖放将目录移动到受监视的树中。选取事件以剪切和粘贴目录(ctrl+x、ctrl+v),而不是拖放(编辑-请参阅下面的更新)。我已经使用JPathWatch重新实现了解决方案,但是这也存在同样的问题。我正在注册标准的ENTRY_CREATE、ENTRY_DELETE和ENTRY_MODIFY并且我还使用了好奇的、文档不足的com.sun.nio.file.ExtendedWatchEventModifie
我正在创建一个回滚功能,这是我想要实现的:在与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
最近在看并发操作时候,例如jmeter进行接口压测(本地自己的springboot2的环境),发现一个有趣的现象,就是关于线程http-nio-8080-exec-1,http-nio-8080-exec-2等等的出现。但是这个线程数不管我的压测数是多少这个线程数不会超过10.抱着好奇的心去搜索了一下相关的文章,但是没有看到比较合适的。然后就只有自己去跟了一下源码。在此自己总结一下。两个问题:1、这个http-nio-8080-exec东西是怎么来的2、为什么这个线程数不超过10把这两个问题其实可以一起归为一个问题来跟代码进行解决:因为我们知道,一般在自定义线程或者线程池名称的时候,我们是可以
在Java7中使用nio.2,当您创建这样的watch服务时:WatchServicewatcher=FileSystems.getDefault().newWatchService();然后,启动后台线程,在无限循环中轮询文件系统事件。此线程的名称是“Thread-n”,这在调查线程转储或分析session期间有点麻烦。我们可以更改该线程的名称吗? 最佳答案 直接看实现,好像不行。如果您不介意一些小技巧,您可以找到线程并重命名它。类似于(//TODO:进行错误检查)SetthreadsBefore=Thread.getAllSta