代码之家  ›  专栏  ›  技术社区  ›  Xtra Coder

整数性能-x32与x64 jvm的30-50倍差异?

  •  14
  • Xtra Coder  · 技术社区  · 6 年前

    long ,但它的调用相当频繁-它的总使用量约占程序总时间的30-40%,而其他部分似乎“更重”。

    我通常在x32jvm上运行不需要内存的程序,但是假设64位类型有问题,我尝试在x64jvm上运行同样的程序-‘livescenario’的总体性能提高了2-3倍。在这之后,我为特定方法的操作创建了JMH基准,并对x32和x64 jvm上的差异感到震惊-多达50次。

    我会接受大约2倍慢的X32JVM(较小的字大小),但我没有任何线索,30-50次可能来自哪里。 你能解释清楚吗?


    对评论的答复 :

    • 我重写了测试代码来“返回一些东西”并避免了“死代码消除”—它似乎没有改变“x32”的任何东西,但是“x64”上的一些方法速度明显变慢了。
    • 两个测试都是在“client”下运行的。在'-server'下运行没有明显的效果。

    • “test code”是错误的:因为“没有返回值”,它允许JVM执行“死代码消除”或其他任何优化,而且“x32 JVM”所做的优化似乎比“x64 JVM”少,这导致了x32和x64之间的显著“错误”差异

    以下是结果(注: ? 10?? 是否在Windows上没有打印特殊字符-它是用科学符号写成的,在0.001 s/op以下的字符,用10e-?)

    x32 1.8.0_152
    
    Benchmark                Mode  Score Units    Score (with 'return')
    IntVsLong.cycleInt       avgt  0.035  s/op    0.034   (?x slower vs. x64)
    IntVsLong.cycleLong      avgt  0.106  s/op    0.099   (3x slower vs. x64) 
    IntVsLong.divDoubleInt   avgt  0.462  s/op    0.459
    IntVsLong.divDoubleLong  avgt  1.658  s/op    1.724   (2x slower vs. x64)
    IntVsLong.divInt         avgt  0.335  s/op    0.373
    IntVsLong.divLong        avgt  1.380  s/op    1.399
    IntVsLong.l2i            avgt  0.101  s/op    0.197   (3x slower vs. x64)  
    IntVsLong.mulInt         avgt  0.067  s/op    0.068
    IntVsLong.mulLong        avgt  0.278  s/op    0.337   (5x slower vs. x64)
    IntVsLong.subInt         avgt  0.067  s/op    0.067   (?x slower vs. x64)
    IntVsLong.subLong        avgt  0.243  s/op    0.300   (4x slower vs. x64)
    
    x64 1.8.0_152
    
    Benchmark                Mode  Score Units    Score (with 'return')
    IntVsLong.cycleInt       avgt ? 10??  s/op   ? 10??
    IntVsLong.cycleLong      avgt  0.035  s/op    0.034
    IntVsLong.divDoubleInt   avgt  0.045  s/op    0.788 (was dead)
    IntVsLong.divDoubleLong  avgt  0.033  s/op    0.787 (was dead)
    IntVsLong.divInt         avgt ? 10??  s/op    0.302 (was dead)
    IntVsLong.divLong        avgt  0.046  s/op    1.098 (was dead)
    IntVsLong.l2i            avgt  0.037  s/op    0.067
    IntVsLong.mulInt         avgt ? 10??  s/op    0.052 (was dead)
    IntVsLong.mulLong        avgt  0.040  s/op    0.067
    IntVsLong.subInt         avgt ? 10??  s/op   ? 10??
    IntVsLong.subLong        avgt  0.075  s/op    0.082
    

    这是(固定的)基准代码

    import org.openjdk.jmh.annotations.Benchmark;
    
    public class IntVsLong {
    
        public static int N_REPEAT_I  = 100_000_000;
        public static long N_REPEAT_L = 100_000_000;
    
        public static int CONST_I = 3;
        public static long CONST_L = 3;
        public static double CONST_D = 3;
    
        @Benchmark
        public void cycleInt() throws InterruptedException {
            for( int i = 0; i < N_REPEAT_I; i++ ) {
            }
        }
    
        @Benchmark
        public void cycleLong() throws InterruptedException {
            for( long i = 0; i < N_REPEAT_L; i++ ) {
            }
        }
    
        @Benchmark
        public int divInt() throws InterruptedException {
            int r = 0;
            for( int i = 0; i < N_REPEAT_I; i++ ) {
                r += i / CONST_I;
            }
            return r;
        }
    
        @Benchmark
        public long divLong() throws InterruptedException {
            long r = 0;
            for( long i = 0; i < N_REPEAT_L; i++ ) {
                r += i / CONST_L;
            }
            return r;
        }
    
        @Benchmark
        public double divDoubleInt() throws InterruptedException {
            double r = 0;
            for( int i = 1; i < N_REPEAT_L; i++ ) {
                r += CONST_D / i;
            }
            return r;
        }
    
        @Benchmark
        public double divDoubleLong() throws InterruptedException {
            double r = 0;
            for( long i = 1; i < N_REPEAT_L; i++ ) {
                r += CONST_D / i;
            }
            return r;
        }
    
        @Benchmark
        public int mulInt() throws InterruptedException {
            int r = 0;
            for( int i = 0; i < N_REPEAT_I; i++ ) {
                r += i * CONST_I;
            }
            return r;
        }
    
        @Benchmark
        public long mulLong() throws InterruptedException {
            long r = 0;
            for( long i = 0; i < N_REPEAT_L; i++ ) {
                r += i * CONST_L;
            }
            return r;
        }
    
        @Benchmark
        public int subInt() throws InterruptedException {
            int r = 0;
            for( int i = 0; i < N_REPEAT_I; i++ ) {
                r += i - r;
            }
            return r;
        }
    
        @Benchmark
        public long subLong() throws InterruptedException {
            long r = 0;
            for( long i = 0; i < N_REPEAT_L; i++ ) {
                r += i - r;
            }
            return r;
        }
    
        @Benchmark
        public long l2i() throws InterruptedException {
            int r = 0;
            for( long i = 0; i < N_REPEAT_L; i++ ) {
                r += (int)i;
            }
            return r;
        }
    
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Dubas    6 年前

    有很多变量需要检查。

    如果我们只看使用64位的处理器,您可以在同一步骤中向CPU寄存器寻址更多操作,因为它使用的是八位字节,而不是每个注册表四个进程。这样可以提高操作性能和内存分配。另外,一些CPU只允许高级功能在64位模式下运行

    如果你使用的是像windows10这样的现代操作系统,你需要考虑到操作系统使用WOW64(x86模拟器)运行32位应用程序

    帮助医生: