引言
这是一篇性能比较的文章,不分析实现原理。主要是对比Java几种常见的文件写入方式
测试代码
主要分析Stream、Stream+Buffer和mmap三种方式,对应的大致代码如下
public static void testBasicFileIO(List<Persona> list, String path) throws Exception {
File file = new File(path);
if (file.exists()){
file.delete();
}
FileOutputStream out = new FileOutputStream(file);
long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
out.write(list.get(i).toString().getBytes());
}
long costTime = System.currentTimeMillis()-startTime;
System.out.println("testBasicFileIO cost:"+costTime);
}
public static void testBufferedFileIO(List<Persona> list, String path) throws Exception {
File file = new File(path);
if (file.exists()){
file.delete();
}
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
out.write(list.get(i).toString().getBytes());
}
long costTime = System.currentTimeMillis()-startTime;
System.out.println("testBufferedFileIO cost:"+costTime);
}
public static void testMmapWrite(List<Persona> list, String path) throws Exception {
File file = new File(path);
if (file.exists()){
file.delete();
}
RandomAccessFile raf = new RandomAccessFile(path, "rw");
FileChannel rafchannel = raf.getChannel();
//mmap 使得jvm堆和pageCache有一块映射空间
MappedByteBuffer map = rafchannel.map(FileChannel.MapMode.READ_WRITE, 0, 4096 * 1024 * 250); // 1000M的pageCache大小
long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
map.put(list.get(i).toString().getBytes());
}
long costTime = System.currentTimeMillis()-startTime;
System.out.println("mmap cost:"+costTime);
}
效果比较
写1M数据效果如下
写10M数据效果如下
写100M效果如下
总结
通过比较能看到在高频写数据到磁盘时,mmap的性能非常显著,有类似的场景时可以优先考虑mmap。当然最好是自己做下基准测试