gpt4 book ai didi

java - 整数性能 - x32 与 x64 jvm 相差 30-50 倍?

转载 作者:搜寻专家 更新时间:2023-10-30 19:47:20 26 4
gpt4 key购买 nike

最近我遇到了一件非常奇怪的事情——一种方法在性能分析器下非常慢,没有明显的原因。它包含很少的 long 操作,但被调用得相当频繁 - 它的总体使用量约为总程序时间的 30-40%,而其他部分似乎“更重”。

我通常在 x32 JVM 上运行非内存消耗型程序,但假设我遇到了 64 位类型的问题,我尝试在 x64 JVM 上运行相同的程序——“实时场景”中的整体性能提高了 2-3 倍.之后,我为特定方法的操作创建了 JMH 基准测试,并对 x32 和 x64 JVM 上的差异感到震惊 - 高达 50 倍。

我会“接受”大约慢 2 倍的 x32 JVM(更小的字长),但我不知道 30-50 倍可能来自哪里。 你能解释一下这种巨大的差异吗?


回复评论:

  • 我重写了测试代码以“返回一些东西”并避免“死代码消除”——它似乎没有为“x32”改变任何东西,但“x64”上的一些方法变得非常慢。
  • 两项测试均在“客户端”下运行。在“-server”下运行没有明显效果。

看来我的问题的答案是

  • “测试代码”是错误的:由于“无返回值”,它允许 JVM 进行“死代码消除”或任何其他优化,并且看起来“x32 JVM”所做的此类优化少于“x64 JVM” -这导致了 x32 和 x64 之间如此显着的“错误”差异
  • “正确测试代码”的性能差异高达 2 到 5 倍 - 这似乎是合理的

这是结果(注意:?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;
}

}

最佳答案

有很多变量需要检查。

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

如果您使用相同的 CPU 执行测试,请往上看,您需要考虑到要执行 32 位指令,CPU 需要在虚拟模式或保护模式下运行,运行速度比真正的 32 位 CPU 慢.此外,一些指令集扩展可能无法使用 32 位模式启用,例如 SSE-SIMD 或 AVX 可能会提高一些操作速度。

此外,如果您使用的是 Windows 10 等现代操作系统,则需要考虑该操作系统使用 WOW64(x86 模拟器)运行 32 位应用程序

帮助文档:

关于java - 整数性能 - x32 与 x64 jvm 相差 30-50 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51134045/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com