目录
在之前写的文章基础上
https://blog.csdn.net/zlpzlpzyd/article/details/135247283
以 1GB 的文件为例比较
200 | 500 | 1024(1KB) | 2KB | 4KB | 8KB | 16KB | 32KB | 64KB | 128KB | 256KB | 512KB | 1MB | 8MB | 64MB | 128MB | 256MB | 512MB | |
BufferedInputStream | 761 | 665 | 450 | 448 | 458 | 457 | 282 | 251 | 220 | 204 | 204 | 203 | 487 | 549 | 627 | 723 | 785 | 911 |
HeapByteBuffer | 6125 | 2677 | 1489 | 886 | 605 | 419 | 298 | 251 | 248 | 204 | 251 | 235 | 290 | 282 | 377 | 393 | 454 | 525 |
DirectByteBuffer | 5786 | 2526 | 1419 | 849 | 553 | 380 | 265 | 204 | 173 | 188 | 173 | 173 | 203 | 188 | 219 | 253 | 220 | 292 |
以 2.45GB 的文件为例比较
200 | 500 | 1024(1KB) | 2KB | 4KB | 8KB | 16KB | 32KB | 64KB | 128KB | 256KB | 512KB | 1MB | 8MB | 64MB | 128MB | 256MB | 512MB | |
BufferedInputStream | 1458 | 1373 | 872 | 925 | 894 | 848 | 629 | 549 | 502 | 455 | 487 | 456 | 1098 | 549 | 627 | 723 | 785 | 911 |
HeapByteBuffer | 12471 | 5419 | 2969 | 1838 | 1208 | 824 | 630 | 518 | 473 | 470 | 465 | 517 | 290 | 282 | 377 | 393 | 454 | 525 |
DirectByteBuffer | 11792 | 5198 | 2857 | 1711 | 1162 | 801 | 514 | 455 | 392 | 361 | 361 | 377 | 203 | 188 | 219 | 253 | 220 | 292 |
由上面的测试结果得知,在缓冲区容量在 8KB、16KB、32KB、64KB、128KB、256KB、512KB 的时候三者耗时持平,但是耗时最短的是 128KB,耗时趋势是开口朝上的抛物线,缓冲区容量达到最佳阈值后再往上增加耗时反而增加。
鉴于 DirectByteBuffer 受限于 jvm 参数 -XX:MaxDirectMemorySize 的大小,默认值为 64MB,在运行时调整为大于 64MB 的缓冲大小后运行时间降低不明显。
BufferedInputStream
在 java 1.0 中添加的缓冲类
验证代码
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.Serializable;
public class TestBufferedInputStream implements Serializable {
public static void main(String[] args) {
long start = System.currentTimeMillis();
File file = new File(Control.PATH);
byte[] bs = new byte[Control.SIZE];
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
while (bis.read(bs) != -1) {
// System.out.println(Arrays.toString(bs));
}
} catch (Throwable e) {
e.printStackTrace();
}
long duration = System.currentTimeMillis() - start;
System.out.println(duration);
}
}
运行时内存使用情况
使用 visualvm中的visual gc插件查看
HeapByteBuffer
在 java 1.4 中添加的缓冲类
验证代码
import java.io.File;
import java.io.FileInputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class TestHeapByteBuffer implements Serializable {
public static void main(String[] args) {
long start = System.currentTimeMillis();
File file = new File(Control.PATH);
ByteBuffer byteBuffer = ByteBuffer.allocate(Control.SIZE);
try (FileChannel fileChannel = new FileInputStream(file).getChannel()) {
while (fileChannel.read(byteBuffer) > 0) {
byteBuffer.clear();
}
} catch (Throwable e) {
e.printStackTrace();
}
long duration = System.currentTimeMillis() - start;
System.out.println(duration);
}
}
运行时内存使用情况
使用 visualvm中的visual gc插件查看
DirectByteBuffer
验证代码
import java.io.File;
import java.io.FileInputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class TestDirectByteBuffer implements Serializable {
public static void main(String[] args) {
long start = System.currentTimeMillis();
File file = new File(Control.PATH);
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(Control.SIZE);
try (FileChannel fileChannel = new FileInputStream(file).getChannel()) {
while (fileChannel.read(byteBuffer) > 0) {
byteBuffer.clear();
}
} catch (Throwable e) {
e.printStackTrace();
}
long duration = System.currentTimeMillis() - start;
System.out.println(duration);
}
}
运行时内存使用情况
使用 visualvm中的visual gc插件查看
总结
HeapByteBuffer 和 DirectByteBuffer 是从 java 1.4 开始添加的类,之前的版本处理缓冲问题需要使用 BufferedInputStream 和 BufferedOutputStream,问题是针对 io 操作只能单向处理,HeapByteBuffer 和 DirectByteBuffer 结合 FileChannel 可以实现对文件的双向处理,即可以通过 FileChannel 实现读写功能。
参考链接