Java 第二个方法调用比第一个方法调用花费的时间少得多

Java 第二个方法调用比第一个方法调用花费的时间少得多,java,performance,memory-management,file-io,benchmarking,Java,Performance,Memory Management,File Io,Benchmarking,我正试图加快我的程序的启动速度,注意到我有一个方法表现得有点奇怪。该程序本身是一个轻量级Java游戏库应用程序,它从文件中读入点并渲染它们。注意的方法是从文件中读取的方法 该方法的奇怪之处在于,我在测试期间调用了它两次,第一次调用需要2837毫秒才能完成,第二次调用只需要1704毫秒 这两个调用之间的差异很小。区别在于,第二个调用在开始对文件进行任何操作之前读取了文件的一半,而第一个调用在开始之前跳过了一行 这就是所讨论的方法: private void initData(final int t

我正试图加快我的程序的启动速度,注意到我有一个方法表现得有点奇怪。该程序本身是一个轻量级Java游戏库应用程序,它从文件中读入点并渲染它们。注意的方法是从文件中读取的方法

该方法的奇怪之处在于,我在测试期间调用了它两次,第一次调用需要2837毫秒才能完成,第二次调用只需要1704毫秒

这两个调用之间的差异很小。区别在于,第二个调用在开始对文件进行任何操作之前读取了文件的一半,而第一个调用在开始之前跳过了一行

这就是所讨论的方法:

private void initData(final int type) throws IOException {
    final List<Vertex> top = new ArrayList<Vertex>();
    final List<Vertex> bot = new ArrayList<Vertex>();
    final BufferedReader input = new BufferedReader(new FileReader(location));
    if(type == 1) {
        while (!input.readLine().contains("lens"));
    } else {
        input.readLine();
    }
    while (input.ready()) {
        final Scanner in = new Scanner(input.readLine());
        while (in.hasNextFloat()) {
            final float x = in.nextFloat();
            final float y = in.nextFloat();
            top.add(new Vertex(x, y, in.nextFloat()));
            bot.add(new Vertex(x, y, in.nextFloat()));
            in.nextFloat();
        }
        if ((in.findInLine("[lens]") != null)
                || (in.findInLine("[thin]") != null)
                || (in.findInLine("[thick]") != null)
                || (in.findInLine("[end]") != null)) {
            break;
        }
    }
    input.close();
    final long start = Diagnostics.getCurrentTime();
    mergeAndSort(top, bot);
    System.out.println("Sort: " + (Diagnostics.getCurrentTime() - start));
}
所有数字都以毫秒为单位。您会注意到,在第二次运行期间,排序几乎花费了四分之一的时间。排序方法在每次运行时都是相同的

每次调用该方法时,都会新创建包含该方法的类


因此,我很好奇为什么第一次调用比第二次调用花费的时间要长几乎一整秒钟。

处理一半文件所花费的时间大约是处理整个文件所花费时间的一半,这一事实使我相信大部分时间都花在对象创建(顶点类的实例化)上

但是,要真正确定发生了什么,唯一的方法是使用分析工具


我从JVisualVM开始,它是JDK发行版的一部分

我添加了内存管理标签,可能与此有关。我对这类问题不是很在行,但使用注释
final
并在循环中声明它们可能是线索。因为在第二次调用中,程序从内存缓存而不是外部源读取数据。这类问题暗示,但是我需要问:对
initData
的两个调用从同一个文件读取(即
location
在调用之间没有变化)?没有。位置保持不变。实际上,它们都处理一半的文件。第一轮中途结束,第二轮中途开始。啊,我明白了。不过,最终的答案是一样的。个人资料,不要猜。
Sort: 15
Initializing: 2836
Sort: 4
Initializing: 1704
Reading info: 27