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;
}
}