当前位置: 首页 > 知识库问答 >
问题:

即时编译器如何优化Java并行流?

田博远
2023-03-14

不久前有人问了一个有趣的问题:

Can (a == 1 && a == 2 && a == 3) evaluate to true in Java?

我决定证明使用Java8流API(确切地说是并行流)是可能的。以下是我的代码,它在非常罕见的情况下工作:

class Race {
    private static int a;

    public static void main(String[] args) {
        IntStream.range(0, 100_000).parallel().forEach(i -> {
            a = 1;
            a = 2;
            a = 3;
            testValue();
        });
    }

    private static void testValue() {
        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        }
    }
}

然后我想,也许是因为潜在的JIT编译器优化?因此,我尝试使用以下VM选项运行代码:

-Djava.compiler=NONE

我禁用了JIT,成功案例的数量显著增加!

即时编译器如何优化并行流,以便优化可能会影响上述代码的执行?

共有1个答案

东门令
2023-03-14

溪流并不重要。同样的效果也可以用两个简单的线程来观察,就像这个答案一样。

a不是volatile时,JIT编译器可以优化(实际上是这样的!)连续赋值。

    a = 1;
    a = 2;
    a = 3;

转化为

    a = 3;

此外,JIT编译器还优化了if(a==1)的

  # {method} {0x000000001e142de0} 'lambda$main$0' '(I)V' in 'Race'
  # parm0:    rdx       = int
  #           [sp+0x20]  (sp of caller)
  0x00000000052eb740: sub     rsp,18h
  0x00000000052eb747: mov     qword ptr [rsp+10h],rbp  ;*synchronization entry
                                                ; - Race::lambda$main$0@-1 (line 8)

  0x00000000052eb74c: mov     r10,76b8940c0h    ;   {oop(a 'java/lang/Class' = 'Race')}
  0x00000000052eb756: mov     dword ptr [r10+68h],3h  ;*putstatic a
                                                ; - Race::lambda$main$0@9 (line 10)

  0x00000000052eb75e: add     rsp,10h
  0x00000000052eb762: pop     rbp
  0x00000000052eb763: test    dword ptr [3470000h],eax
                                                ;   {poll_return}
  0x00000000052eb769: ret

除了方法prologue和eplilogue外,只有一条指令存储值3:

  mov     dword ptr [r10+68h],3h  ;*putstatic a

因此,一旦编译了该方法,System.out.println就永远不会发生。当您看到“成功”时,这些罕见的情况会发生在解释过程中,此时代码尚未JIT编译。

 类似资料:
  • 问题内容: Java编译器(即javac)在生成字节码时不会执行任何优化。是真的吗 如果是这样,那么它可以实现为中间代码生成器以消除冗余并生成最佳代码吗? 问题答案: 如果有的话,只会做很少的优化。 关键是JIT编译器完成了大部分优化工作-如果它具有很多信息,则效果最佳,如果执行优化,其中的一些信息也可能会丢失。如果执行某种形式的循环展开,那么JIT很难以一般的方式自行完成-而且,由于它了解目标平

  • 问题内容: 我目前正在翻译中编写一个针对Java字节码的玩具编译器。 我想知道是否可以在编写.class文件之前在发出的字节码中进行各种简单的窥孔优化的目录,也许是摘要。我实际上知道一些具有此功能的库,但是我想自己实现。 问题答案: 您知道Proguard吗?http://proguard.sourceforge.net/ 这是一个很棒的字节码优化器,它实现了很多优化。请参阅常见问题解答以获取列表

  • 问题内容: 我正在编写一个常量字符串比较函数(用于node.js),并且想为此功能禁用V8的优化编译器;使用命令行标志是不可能的。 我知道,使用(或try / catch语句)块将禁用优化编译器 现在 ,但恐怕这个“功能”(错误)将被固定在未来的版本。 是否有一种不可变(且已记录)的方式来禁用V8的优化编译器? 示例功能: 性能测试只是为了好玩。 问题答案: 如果您想要可靠的方法来执行此操作,则需

  • 问题内容: 假设我在C代码中有类似的内容。我知道您可以使用a 代替,以使编译器不对其进行编译,但是出于好奇,我问编译器是否也可以解决此问题。 我认为这对于Java编译器来说更为重要,因为它不支持。 问题答案: 在Java中,if内的代码甚至都不是已编译代码的一部分。它必须编译,但不会写入已编译的字节码。它实际上取决于编译器,但我不知道没有对它进行优化的编译器。规则在JLS中定义: 优化的编译器可能

  • 如果关闭了编译器优化(gcc-o0...),那么说'volatile'关键字没有区别是可以的吗? 我制作了一些示例“C”程序,并且仅当打开编译器优化时,才在生成的汇编代码中看到易失性和非易失性之间的区别,即((gcc-o1....)。

  • stackoverflow上的几个线程(例如这一个)讨论了不同的优化级别(、、...)在编译Swift应用程序时。 然而,那些帖子与OSX上的开发有关。这些优化似乎可以直接通过Xcode或xcrun()设置。 我想知道在Linux(Ubuntu15.10)上直接使用Swift编译器时,如何切换不同的优化级别。目前,我只是通过调用来构建应用程序,如文档中所示,但我发现没有办法不更改优化级别。