为什么这个Java程序比它的Ada等效程序快1000倍?

为什么这个Java程序比它的Ada等效程序快1000倍?,java,ada,Java,Ada,我有两个程序,只需循环10亿次,然后增加一个整数。我正在对这两种操作进行计时,并比较两种结果。对于Ada程序,我使用GNAT FSF编译器。这两个程序都在Windows上运行。我还尝试运行每种代码的多个代码,并平均测量的持续时间,这显示了相同的结果 我预计有两件事正在发生,要么是我的Ada程序编写得不正确,要么是我对该语言非常陌生,要么是它编写得正确,但Java编译器正在对代码做一些我不知道的事情 以下是Ada计划: with Ada.Text_IO; use Ada.Text_IO; with

我有两个程序,只需循环10亿次,然后增加一个整数。我正在对这两种操作进行计时,并比较两种结果。对于Ada程序,我使用GNAT FSF编译器。这两个程序都在Windows上运行。我还尝试运行每种代码的多个代码,并平均测量的持续时间,这显示了相同的结果

我预计有两件事正在发生,要么是我的Ada程序编写得不正确,要么是我对该语言非常陌生,要么是它编写得正确,但Java编译器正在对代码做一些我不知道的事情

以下是Ada计划:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;

procedure Main is
    c : Integer := 1;

    startTime, endTime : Time;
    milliS : Duration;
begin
    startTime := Clock;
    while c <= 1000000000 loop
        c := c + 1;
    end loop;

    endTime := Clock;
    milliS := (endTime - startTime) * 1000;

    put_line("Runtime = " & Duration'Image(milliS) & " milliseconds.");
end Main;
Java代码:

public class Test {

    public static void main(String[] args) {
        int c = 1;
        long start = System.nanoTime();

        while (c<=1000000000) {
            c = c + 1;
        }

        long stop = System.nanoTime();

        float duration = (float) ((start - stop)/1000000.0);
        System.out.println(duration);
    }
}

Ada直接编译为机器代码,因此我希望它比Java程序快。

Java JIT编译器足够聪明,可以实现循环的优化。它做到了

如果您修改了Java版本,以便在最后打印出c的值,那么您将获得与未优化的Ada版本大致相当的执行时间。如果使用了c的值,则无法优化循环1

Ada直接编译为机器代码,所以我希望它比Java程序更快

Java JIT编译器也会编译为机器代码,但不会立即编译


1-直到我们得到一个全知的JIT编译器,它意识到我们不关注输出:-

Java JIT编译器足够聪明,可以实现循环的优化。它做到了

如果您修改了Java版本,以便在最后打印出c的值,那么您将获得与未优化的Ada版本大致相当的执行时间。如果使用了c的值,则无法优化循环1

Ada直接编译为机器代码,所以我希望它比Java程序更快

Java JIT编译器也会编译为机器代码,但不会立即编译


1-直到我们得到一个全知的JIT编译器,它意识到我们不关注输出:-

我不能复制您的问题

我用你的电脑建立了你的程序

$ gnatmake -gnata -gnato -fstack-check -gnat12 -gnatyO -gnatv -gnati1 -gnatf -gnatn -O3 main.adb
gcc-6 -c -gnata -gnato -fstack-check -gnat12 -gnatyO -gnatv -gnati1 -gnatf -gnatn -O3 main.adb

GNAT 6.3.0 20170516
Copyright 1992-2016, Free Software Foundation, Inc.

Compiling: main.adb
Source file time stamp: 2018-08-01 08:20:21
Compiled at: 2018-08-01 10:20:30
 19 lines: No errors
gnatbind-6 -x main.ali
gnatlink-6 main.ali -fstack-check -O3
$
然后,我使用时间运行程序以检查执行时间:

$ time ./main
Runtime =  0.002000000 milliseconds.
./main  0,00s user 0,00s system 82% cpu 0,005 total
$

如果您不进行优化,那么Ada编译器将尝试确保源文本和机器代码之间尽可能接近匹配,以便于验证您的可执行文件是否正确。-在这种情况下,您当然应该在循环中得到1000次迭代。

我无法复制您的问题

我用你的电脑建立了你的程序

$ gnatmake -gnata -gnato -fstack-check -gnat12 -gnatyO -gnatv -gnati1 -gnatf -gnatn -O3 main.adb
gcc-6 -c -gnata -gnato -fstack-check -gnat12 -gnatyO -gnatv -gnati1 -gnatf -gnatn -O3 main.adb

GNAT 6.3.0 20170516
Copyright 1992-2016, Free Software Foundation, Inc.

Compiling: main.adb
Source file time stamp: 2018-08-01 08:20:21
Compiled at: 2018-08-01 10:20:30
 19 lines: No errors
gnatbind-6 -x main.ali
gnatlink-6 main.ali -fstack-check -O3
$
然后,我使用时间运行程序以检查执行时间:

$ time ./main
Runtime =  0.002000000 milliseconds.
./main  0,00s user 0,00s system 82% cpu 0,005 total
$

如果您不进行优化,那么Ada编译器将尝试确保源文本和机器代码之间尽可能接近匹配,以便于验证您的可执行文件是否正确。-在这种情况下,你当然应该在你的循环中得到1_000_000_000迭代。

运行这里发布的优化为我返回了相同的结果。然而,正如我所说的,我可能没有做正确的事情,我对这门语言是新手。这个测试的主要目标是确定艾达是否给了我一个明显的速度增加,假设两个程序都执行相同的一般计算,但是我没有考虑JIT编译器将删除我的for循环的事实,我宁愿它不这样做…@ USSUR1717351,如果您不希望JIT编译器删除循环,您必须让它做一些有意义的工作,并让Ada实现做同样的事情。还应该注意,JIT编译器做的是客观上正确的事情。1 JIT优化器的目标是使代码在生产环境中尽可能快地运行。它无法解读你的意图。。。以确定这不是生产设置。2即使在进行基准测试时,也应以复制生产性能为目标。这通常是基准测试的重点。3.为了衡量语言结构的性能而进行人工操作的微观基准测试需要仔细编写。。。。在任何情况下。。。因为优化效果。这种无优化行为实际上是特定于GNAT的。大多数其他Ada编译器都会进行一些优化,即使是在最低的优化设置下也是如此。然而,正如我所说的,我可能没有做正确的事情,我对这门语言是新手。这个测试的主要目标是确定艾达是否给了我一个明显的速度增加,假设两个程序都执行相同的一般计算,但是我没有考虑JIT编译器将删除我的for循环的事实,我宁愿它不这样做…@ USSUR1717351,如果您不希望JIT编译器删除循环,您必须让它做一些有意义的工作,并让Ada实现做同样的事情
还要注意,JIT编译器所做的客观上是正确的。1 JIT优化器的目标是使代码在生产环境中尽可能快地运行。它无法解读你的意图。。。以确定这不是生产设置。2即使在进行基准测试时,也应以复制生产性能为目标。这通常是基准测试的重点。3.为了衡量语言结构的性能而进行人工操作的微观基准测试需要仔细编写。。。。在任何情况下。。。因为优化效果。这种无优化行为实际上是特定于GNAT的。大多数其他Ada编译器都会进行一些优化,即使是在最低的优化设置下也是如此。注意:我没有尝试重现OP的结果。注意:我没有尝试重现OP的结果。