Files.readAllLines()执行时间更改

时间:2014-10-23 18:22:12

标签: java

我正在玩不同的方法来读取文件中的数字以及它们的效率,这是我目前正在使用的一种方法:

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是否很聪明并且存储了文件中的值,并且每次都不会重新读取文件?

我很好奇......

2 个答案:

答案 0 :(得分:1)

这将是工作中的磁盘缓存。第一次读取是从磁盘上下来的。第二次读取来自磁盘缓存。

我过去曾对算法进行过性能测试。文件IO和缓存总是妨碍或影响结果。你需要考虑你正在寻找什么样的表现。

如果您正在测试一个完整的系统,那么您将保留文件IO,但是您需要刷新缓存以获得一致的结果。

如果您正在测试算法,请将所有IO保留在计时器之外。

读取文件后移动'startTime = System.nanoTime()'。

答案 1 :(得分:1)

文件IO使用类似于请求分页的技术将文件的一部分加载到物理内存中。磁盘文件页面到物理内存页面的映射由分页操作系统维护。

第一次加载时,会生成页面错误,因为请求的文件页面不在物理内存中。当您尝试再次加载时,将在物理内存中找到一些页面,并且不需要从磁盘重新读取。如果对物理内存中的页面进行任何更改,则页面输出会确保将脏页刷新到磁盘。

您还会注意到这一点:在您最喜欢的文本编辑器中尝试首次打开文件时,需要一段时间。当您关闭文件并重新打开它时,它会加载更快。这是由于磁盘文件页面已经在物理内存中。

当您通过Java重新读取文件时,会发生同样的事情。它是优化重读的操作系统,而不是Java。