场景描述
- 文件大小 8.67G的json文件,一共670万行。
- 服务器内存:2g。(只能读取一定缓冲数据,然后处理后继续读取,不能一次性加载到内存)
- 读取文件的内容出来,并未做业务处理。
读取方式和性能对比
- 使用org.pache.commons.io.FileUtils.lineIterator,按行读,耗时:79.10s
- 使用RandomAccessFile读取文件,耗时【测试缓冲区在40k性能较好】:
- 缓冲区1k,耗时101.10s
- 缓冲区10k,耗时28.13s
- 缓冲区20k,耗时24.08s
- 缓冲区30k,耗时23.29s
- 缓冲区40k,耗时23.1s
- 使用BufferedInputStream读取文件,耗时【测试在缓冲区为40k性能最好】:
- 缓冲区1k,耗时:75.7s
- 缓冲区10K,耗时:27.10s
- 缓冲区20k,耗时:22.19s
- 缓冲区30k,耗时:21.55s
- 缓冲区40k,耗时: 20.17s
- 缓冲区50k,耗时:20.44s
- 缓冲区60k,耗时:21.24s
- 缓冲区100k,耗时:27.8s
- 缓冲区1M,耗时:30s
- 使用Scanner读文件,FileOutputStream写文件,耗时:206.78s
- 使用NIO,FileChannel读写文件,耗时【测试在每次读取35-40k性能最好】:
- NIO每次读取10k,耗时:26.03s (内存大约占用100m)
- NIO每次读取20k,耗时:22.03s (内存大约占用100m)
- NIO每次读取30k,耗时:23.03s (内存大约占用100m)
- NIO每次读取35k,耗时:19.88ss (内存大约占用100m)
- NIO每次读取40k,耗时:19.75s (内存大约占用100m)
- NIO每次读取50k,耗时:26.75s (内存大约占用100m)
- NIO每次读取100k,耗时:21.3s (内存大约占用100m)
- NIO每次读取0.5M,耗时:23.48s (内存大约占用200-300m)
- NIO每次读取5M,耗时:28.97s (内存大约占用800-1200m)
- NIO每次读取10M,耗时:30.06s (内存大约占用800-1200m)
- NIO每次读取20M,耗时:26.10s (内存大约占用800-1300m)
- NIO每次读取30M,耗时:40.10s (内存大约占用2000-2600m)
为什么scnner读取效率最慢
- 基本来说,缓冲区读取比scanner快了至少10倍
- bufferReader缓冲区大小为8KB,Scanner的缓冲区大小为1Kb.
- bufferReader知识简单的读取字符序列。而Scanner对输入数据要做正则解析。
代码示例
- org.pache.commons.io.FileUtils.lineIterator
public static void main(String[] args) throws IOException {
String path = "D:\\模拟数据\\1.txt";
LineIterator it = FileUtils.lineIterator(new File(path), "UTF-8");
Integer counter = 1;
long startTime = System.currentTimeMillis();
while (it.hasNext()) {
System.out.println("_-------------" + counter++);
String line = it.nextLine();
}
long endTime = System.currentTimeMillis();
System.out.println("耗费时间:" + (endTime-startTime