V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chaoschick
V2EX  ›  程序员

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

  •  
  •   chaoschick · 334 天前 · 3865 次点击
    这是一个创建于 334 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 条回复    2023-12-27 14:32:47 +08:00
    xtreme1
        1
    xtreme1  
       334 天前   ❤️ 3
    tool2d
        2
    tool2d  
       334 天前   ❤️ 1
    @xtreme1 被完全优化掉的不算。


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

    时间就正常了。
    chaoschick
        3
    chaoschick  
    OP
       334 天前
    @xtreme1 能解释一下为什么两者性能如此悬殊的原因吗
    chaoschick
        4
    chaoschick  
    OP
       334 天前
    @tool2d 我试试
    hefish
        5
    hefish  
       334 天前
    java 的编译器高级。全优化掉了。
    chaoschick
        6
    chaoschick  
    OP
       334 天前
    @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
        7
    wdlth  
       334 天前
    我在我的电脑测试结果是:
    0 us
    0.000 ms
    tool2d
        8
    tool2d  
       334 天前
    @chaoschick 4 秒正常的啊,我这里也是 4 秒。

    0 秒那种都是编译器把循环优化掉了。
    diivL
        9
    diivL  
       334 天前
    gcc duff2.c -O3 && ./a.out
    chaoschick
        10
    chaoschick  
    OP
       334 天前
    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
        11
    chaoschick  
    OP
       334 天前
    @diivL [admin@iZt4ngr7j75qbzgg9ilsifZ c]$ gcc duff2.c -O3 && ./a.out
    3688484 us
    3688.484 ms
    diivL
        12
    diivL  
       334 天前   ❤️ 1
    @chaoschick 你用的是 #6 的代码吗? 用你主贴的代码,然后用 gcc duff2.c -O3 && ./a.out
    chaoschick
        13
    chaoschick  
    OP
       334 天前
    @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
        14
    Ericcccccccc  
       334 天前
    在 main 里做性能测试是无效行为.

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