• 请不要在回答技术问题时复制粘贴 AI 生成的内容
chaoschick
V2EX  ›  程序员

相同的 for 循环 为什么 Java 比 c 的速度快?

  •  
  •   chaoschick · Dec 26, 2023 · 4961 views
    This topic created in 1051 days ago, the information mentioned may be changed or developed.
    Java

    public class DuffDevice {

    private static int duff2(int count) {
    int i = 0;
    do {
    ++i;
    } while (--count >0);
    return i;
    }

    public static void main(String[] args) {
    int duff;
    long start, end;
    DuffDevice duffDevice = new DuffDevice();

    start = System.currentTimeMillis();
    duff = duff2(Integer.MAX_VALUE - 7);
    end = System.currentTimeMillis();
    System.out.println(duff + " " + (end - start) + " ms");
    }
    }

    C
    #include <sys/time.h>
    #include <stdio.h>

    int duff(int count) {
    }

    int main(int argc, char* argv[]) {
    struct timeval start_time, end_time;

    gettimeofday(&start_time, NULL);

    long count = 2147483640;
    long i = 0;

    do {
    ++i;
    } while (--count);

    gettimeofday(&end_time, NULL);

    int total_time = 1000000 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec);
    printf("%d us", total_time);
    printf("\n");
    printf("%.3f ms", (double) total_time / 1000);
    printf("\n");

    printf("%l", i);
    return 0;
    }

    Java 耗时情况
    2 ms

    C 耗时情况
    4638.628 ms

    性能怎么会相差这么大?
    23 replies  •  2023-12-27 14:32:47 +08:00
    tool2d
    tool2d
    Dec 26, 2023❤️1
    2
    @xtreme1 被完全优化掉的不算。

    把
    long i = 0;
    改成
    volatile long i = 0;

    时间就正常了。
    chaoschick
    chaoschick
    OP
    Dec 26, 2023
    3
    @xtreme1 能解释一下为什么两者性能如此悬殊的原因吗
    chaoschick
    chaoschick
    OP
    Dec 26, 2023
    4
    @tool2d 我试试
    hefish
    hefish
    Dec 26, 2023
    5
    java 的编译器高级。全优化掉了。
    chaoschick
    chaoschick
    OP
    Dec 26, 2023
    6
    @tool2d [admin@iZt4ngr7j75qbzgg9ilsifZ c]$ cat duff2.c
    #include <sys/time.h>
    #include <stdio.h>

    int main(int argc, char* argv[]) {
    struct timeval start_time, end_time;

    gettimeofday(&start_time, NULL);

    long count = 2147483640;
    volatile long i = 0;

    do {
    ++i;
    } while (--count);

    gettimeofday(&end_time, NULL);

    int total_time = 1000000 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec);
    printf("%d us", total_time);
    printf("\n");
    printf("%.3f ms", (double) total_time / 1000);
    printf("\n");

    printf("%l", i);
    return 0;
    }
    [admin@iZt4ngr7j75qbzgg9ilsifZ c]$ gcc duff2.c && ./a.out
    4621705 us
    4621.705 ms
    wdlth
    wdlth
    Dec 26, 2023
    7
    我在我的电脑测试结果是:
    0 us
    0.000 ms
    tool2d
    tool2d
    Dec 26, 2023
    8
    @chaoschick 4 秒正常的啊,我这里也是 4 秒。

    0 秒那种都是编译器把循环优化掉了。
    diivL
    diivL
    Dec 26, 2023
    9
    gcc duff2.c -O3 && ./a.out
    chaoschick
    chaoschick
    OP
    Dec 26, 2023
    10
    public class DuffDevice {

    private static long duff2(long count) {
    long i = 0;
    do {
    ++i;
    } while (--count >0);
    return i;
    }

    public static void main(String[] args) {
    long duff;
    long start, end;
    DuffDevice duffDevice = new DuffDevice();

    start = System.currentTimeMillis();
    duff = duff2((long) Integer.MAX_VALUE - 7);
    end = System.currentTimeMillis();
    System.out.println(duff + " " + (end - start) + " ms");
    }
    }

    输出
    2147483640 639 ms

    我改了一下 i 值的类型 耗时 变长了
    所以 应该没把循环优化掉吧
    chaoschick
    chaoschick
    OP
    Dec 26, 2023
    11
    @diivL [admin@iZt4ngr7j75qbzgg9ilsifZ c]$ gcc duff2.c -O3 && ./a.out
    3688484 us
    3688.484 ms
    diivL
    diivL
    Dec 26, 2023❤️1
    12
    @chaoschick 你用的是 #6 的代码吗? 用你主贴的代码,然后用 gcc duff2.c -O3 && ./a.out
    chaoschick
    chaoschick
    OP
    Dec 26, 2023
    13
    @diivL #include <sys/time.h>
    #include <stdio.h>

    int main(int argc, char* argv[]) {
    struct timeval start_time, end_time;

    gettimeofday(&start_time, NULL);

    long count = 2147483640;
    long i = 0;

    do {
    ++i;
    } while (--count);

    gettimeofday(&end_time, NULL);

    int total_time = 1000000 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec);
    printf("%d us", total_time);
    printf("\n");
    printf("%.3f ms", (double) total_time / 1000);
    printf("\n");

    printf("%l", i);
    return 0;
    }
    [admin@iZt4ngr7j75qbzgg9ilsifZ c]$ gcc duff2.c -O3 && ./a.out
    1 us
    0.001 ms

    这是优化掉 for 循环了吗?
    Ericcccccccc
    Ericcccccccc
    Dec 26, 2023
    14
    在 main 里做性能测试是无效行为.

    而且 java 里有各种 jit, osr 之类的高级优化手段
    iseki
    iseki
    Dec 26, 2023 via Android
    15
    此外 Java 的 volatile 有额外的语义,所以也没法和 C 对应,这样做 microbench 可能你们很难说明什么问题
    msg7086
    msg7086
    Dec 26, 2023
    16
    > 为什么
    因为优化不一样。如果 Java 比 C 快很多,那说明 Java 上优化得比 C 狠,反之亦然。
    Inn0Vat10n
    Inn0Vat10n
    Dec 26, 2023
    17
    你这里出现这么离谱的结果, 首要原因是编译 C 代码时没开优化
    Cookmilk
    Cookmilk
    Dec 27, 2023 via iPhone
    18
    C 是直接跑在电脑的 CPU 里,java 跑在虚拟机 CPU 里。测试 for 循环毫无意义。应该测试某一个算法。比如加密算法或者 md5 等等
    mangojiji
    mangojiji
    Dec 27, 2023
    19
    又见达夫设备。 ...
    chaoschick
    chaoschick
    OP
    Dec 27, 2023 via Android
    20
    以前我一直以为编译器优化能提升的性能很小,这次真是长见识了
    PTLin
    PTLin
    Dec 27, 2023❤️1
    21
    这种代码不长的,而且是循环引起的性能问题,建议直接看汇编/字节码,来确定问题以及验证猜想。
    或者用完整的性能测试框架测试,避免出现一个优化后测试的,一个还是调试模式测试的的这种低级问题。
    debuggerx
    debuggerx
    Dec 27, 2023
    22
    [为什么下面程序递归计算斐波那契数列 java 比 c++要快 - RednaxelaFX 的回答]( https://www.zhihu.com/question/56683164/answer/150190561)
    LiaoMatt
    LiaoMatt
    Dec 27, 2023
    23
    C 代码的变量用 register 修饰会不会更快
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2304 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 12:31 · PVG 20:31 · LAX 04:31 · JFK 07:31
    ♥ Do have faith in what you're doing.