比如我有这样的表情
if (DEBUG) log.debug("hello")
scala或java中有没有一种方法可以以这种方式启动
DEBUG
变量,这样如果它是false
,整个表达式就会在运行时被删除?
我猜测分支会在运行时被 JIT 删除,但真的是这样吗? 有没有办法“提示”JIT去做?
如果某个值是常量,请将其标记为
static final
。这也可以保护您免受意外修改。如果您需要每个实例的变量(例如在构造函数中设置),只需将其设置为final
。 JIT 也将能够利用该信息。
但是 JIT 并不是唯一能够使用该信息的编译器。
假设您有以下 Java 代码:
class A{
static final boolean DEBUG = false;
void a(){
if(DEBUG){
System.out.println("Hello World");
}
}
}
然后你看一下
javac
生成的字节码(使用 javap -c A.class
),它看起来像这样:
Compiled from "A.java"
class A {
static final boolean DEBUG;
A();
Code:
0: aload_0
1: invokespecial #3 // Method java/lang/Object."<init>":()V
4: return
void a();
Code:
0: return
}
如您所见,
javac
已经能够消除 static final
字段 if 它们是用文字初始化的。但这也意味着如果更改 DEBUG
变量,则需要使用该字段重新编译所有类。
如果您想避免这种情况,并且仍然确保 JIT 在运行时对其进行优化,您可以执行以下操作:
static final boolean DEBUG = initDebug();
private static boolean initDebug(){
return DEBUG;
}
现在,即使
javac
无法内联它,JIT 也可以检测到某些分支从未执行。在这种情况下,它通常会用去优化陷阱替换该分支(如果需要优化,JIT 会去优化代码并重新开始)。这种情况只会发生在经常执行的代码上(对于其他代码,您不需要关心,因为它通常与性能无关)。
在很多情况下,你认为对性能重要的事情其实是无关紧要的。如果您认为应该优化某些内容,请首先检查它是否确实是瓶颈。您可以为此使用火焰图或类似工具。
一旦你开始优化一段代码,首先使用 JMH 来实际测量没有优化的性能。完成优化后,再次测量(使用 JMH)并检查它是否有所改进。如果您没有看到显着的改进(或者甚至变得更糟),则优化可能不值得。您不知道哪些代码会表现良好,并且您的优化可能会使性能变得更糟,因为它们可能会使某些 JIT 优化变得更加困难或出现类似的问题。