传统I/O和NIO性能基准测试不同点
- 传统I/O:基于流(Stream)的操作,一次一个字节或一个字符地处理数据。操作相对简单直观,但效率较低,特别是在处理大文件或高并发场景下。因为每次读写都可能涉及系统调用,频繁的系统调用开销较大。
- NIO:基于缓冲区(Buffer)和通道(Channel)的操作。数据先被读入缓冲区,然后再从缓冲区写入目标位置,减少了系统调用次数,提高了效率。NIO支持非阻塞I/O,在高并发场景下能更好地利用系统资源。
代码实现
传统I/O实现文件复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class TraditionalIOFileCopy {
public static void main(String[] args) {
String sourceFilePath = "sourceFile.txt";
String targetFilePath = "targetFile.txt";
try (InputStream inputStream = new FileInputStream(sourceFilePath);
OutputStream outputStream = new FileOutputStream(targetFilePath)) {
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO实现文件复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class NIOFileCopy {
public static void main(String[] args) {
String sourceFilePath = "sourceFile.txt";
String targetFilePath = "targetFile.txt";
try (FileInputStream inputStream = new FileInputStream(sourceFilePath);
FileOutputStream outputStream = new FileOutputStream(targetFilePath);
FileChannel inputChannel = inputStream.getChannel();
FileChannel outputChannel = outputStream.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inputChannel.read(buffer) != -1) {
buffer.flip();
outputChannel.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
不同场景下性能差异原因分析
- 文件大小:
- 小文件:传统I/O和NIO性能差异可能不明显。因为小文件读写操作本身耗时短,系统调用开销占比相对较小,NIO减少系统调用的优势难以体现。
- 大文件:NIO性能优势明显。NIO通过缓冲区减少系统调用次数,减少了内核态和用户态切换开销,提高了读写效率。传统I/O频繁系统调用,开销大,性能较低。
- 并发访问:
- 低并发:两者性能差异不大。因为系统资源相对充足,传统I/O即使频繁系统调用也能满足需求。
- 高并发:NIO性能更优。NIO支持非阻塞I/O,一个线程可以管理多个通道,减少线程数量,降低线程上下文切换开销,能更好地利用系统资源处理高并发请求。传统I/O基于阻塞I/O,每个连接需要一个独立线程处理,高并发时线程数量过多,性能下降。