我正在浏览帖子,它说使用BufferedReader或MappedByteBuffer。我决定使用291.0 MB文件自行测试,但仍然无法决定
BufferedReader reader = new BufferedReader(new FileReader("/Users/rachana/part-00000"));
String line = null;
while((line = reader.readLine())!=null) {
System.out.println(line);
}
~~~~~~ Heap utilization in MB ~~~~~~
Start Date 21:10:20
End Date 21:17:48
Time used 448 second
7.50 min
Used Memory In MB:28
Free Memory:81
Total Memory:109
Max Memory:1820
使用MappedByteBuffer
RandomAccessFile aFile = new RandomAccessFile
("/Users/rachana/part-00000", "r");
FileChannel inChannel = aFile.getChannel();
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
buffer.load();
for (int i = 0; i < buffer.limit(); i++)
{
System.out.print((char) buffer.get());
}
buffer.clear(); // do something with the data and clear/compact it.
inChannel.close();
aFile.close();
~~~~~~ Heap utilization in MB ~~~~~~
Start Date 21:20:40
End Date 21:33:52
Time used 792 sec / 13.2 min
Used Memory In MB:4
Free Memory:104
Total Memory:109
Max Memory:1820
它明确指出MappedByteBuffer使用更少的内存但更多的时间,因为BufferedReader使用更多内存但时间更少。
我正在尝试使用MappedByteBuffer找到平衡读取线的方法。
任何建议都会有所帮助
答案 0 :(得分:6)
您正在做的最慢的部分是打印到屏幕上。我建议你不要这样做,你会很好,MemoryMapped文件要快得多(如果你不是一次打印一个字符到控制台)
注意:除非您使用的是IS-8859-1或US-ASCII编码的文本文件,否则这两个不可互换。 BufferedReader用于文本,内存映射文件用于二进制文件。
BTW如果忽略您执行的GC数量,则无需查看使用的内存。如果您只关心在开始和结束时使用的内存,您应该在测量之前使用System.gc()进行完整的GC,并且我希望在两种情况下都会看到一个小的随机差异(可能是负数)。 / p>
如果你关于分配的情况,你需要更大的伊甸园大小,例如2 GB开始为空(在完整GC之后)或您可以使用分析器来测量分配。在第一种情况下,字符串将分配最多的数据,在第二种情况下,写入控制台将创建最多。
答案 1 :(得分:2)
显然,这不可能是真的,事实并非如此。您使用它明确指出MappedByteBuffer使用的内存较少,但BufferedReader使用更多内存但时间更短的时间更长。
MappedByteBuffer,
而不是BufferedReader
将整个300MB文件映射到内存中。解释是MappedByteBuffer
内存不是来自堆。它使用内存,与文件大小一样多,远比BufferedReader
代码更多。你只是在这里测量它。
同样地,你的时间测量也是无效的,因为它们由System.out.println()控制,它不是输入,并且希望它不是最终应用程序的一部分。
因此,您的基准测试在各方面都完全无效。
使用BufferedReader
。你可以每秒读取数百万行。它足够快。
答案 2 :(得分:1)
我会选择第一个,除非你真的试图刮掉桶以进行内存优化。
原因:
答案 3 :(得分:1)
在进行文件I / O时,您应该记住,I / O操作可能比代码中CPU所做的任何工作都要慢得多。
但还有其他一些考虑因素。优化往往会使代码更复杂,更难理解。为了理解您的MappedByteBuffer
代码,读者需要了解MappedByteBuffer
除了需要了解文件输入所需的所有内容之外的其他工作方式。
通常会进行文件读取。因此,Java已经提供了帮助您的代码,这一点不应该让您感到惊讶。该代码将由专家编写,经过测试和调试。除非您有特殊要求,否则应始终使用此类代码而不是自己编写代码。也就是说,我建议使用BufferedReader
(您的第一种方法)。