我正在玩不同的方法来读取文件中的数字以及它们的效率,这是我目前正在使用的一种方法:
public static long getNumbers1() {
final long startTime = System.nanoTime();
try
{
String input = new String(Files.readAllBytes(file.toPath()));
String[] stringNumbers = input.split("\\W");
int[] numbers = new int[stringNumbers.length];
for(int index = 1;index < stringNumbers.length;index++)
{
numbers[index] = Integer.parseInt(stringNumbers[index]);
}
}
catch (IOException e)
{
e.printStackTrace();
}
final long endTime = System.nanoTime();
System.out.println(endTime + " | " + startTime + " | " + (endTime - startTime));
return endTime - startTime;
}
file
在全球范围内声明:
private static File file = new File(System.getProperty("user.dir") + "/data/numtest.txt");
然后通过以下方式运行此方法:
for (int index = 0;index < 10;index++)
{
getNumbers1();
}
控制台中打印的内容如下:
15395409456370 | 15395397323226 | 12133144
15395410416178 | 15395410090933 | 325245
15395411137449 | 15395410835563 | 301886
15395411806342 | 15395411515427 | 290915
15395412389234 | 15395412097611 | 291623
15395412780660 | 15395412529737 | 250923
15395413168193 | 15395412912315 | 255878
15395413538738 | 15395413302679 | 236059
15395413948214 | 15395413665792 | 282422
15395414329376 | 15395414083762 | 245614
您会注意到,第一个“运行时间”值(第三个值)在文件的第一次读取中明显大于后续读数。无论我运行程序多少次,或者我执行for循环运行多少次(100或100000),第一个值总是要大得多。为什么会这样?我可以阻止它发生吗? JAVA是否很聪明并且存储了文件中的值,并且每次都不会重新读取文件?
我很好奇......
答案 0 :(得分:1)
这将是工作中的磁盘缓存。第一次读取是从磁盘上下来的。第二次读取来自磁盘缓存。
我过去曾对算法进行过性能测试。文件IO和缓存总是妨碍或影响结果。你需要考虑你正在寻找什么样的表现。
如果您正在测试一个完整的系统,那么您将保留文件IO,但是您需要刷新缓存以获得一致的结果。
如果您正在测试算法,请将所有IO保留在计时器之外。
读取文件后移动'startTime = System.nanoTime()'。
答案 1 :(得分:1)
文件IO使用类似于请求分页的技术将文件的一部分加载到物理内存中。磁盘文件页面到物理内存页面的映射由分页操作系统维护。
第一次加载时,会生成页面错误,因为请求的文件页面不在物理内存中。当您尝试再次加载时,将在物理内存中找到一些页面,并且不需要从磁盘重新读取。如果对物理内存中的页面进行任何更改,则页面输出会确保将脏页刷新到磁盘。
您还会注意到这一点:在您最喜欢的文本编辑器中尝试首次打开文件时,需要一段时间。当您关闭文件并重新打开它时,它会加载更快。这是由于磁盘文件页面已经在物理内存中。
当您通过Java重新读取文件时,会发生同样的事情。它是优化重读的操作系统,而不是Java。