JVM 是否通过在同一方法中存储相似方法调用的结果来修复我的低效代码?

Does the JVM fix my inefficient code by storing the results of similar method calls within the same method?

给定代码

if (linkedHashMap.get(string) == null) { 
  linkedHashMap.put(string, object);
} else { 
  linkedHashMap.get(string).increment();
}

Interputer/JVM 是否决定:linkedHashMap.get(string) 被使用了两次,因此为此调用分配了一个变量,或者它只是低效地执行了两次完全相同的调用?

没有Interputer这样的东西。即时编译器可能会识别重复,但前提是被调用的方法足够简单可以内联,HashMap.get 可能不是这种情况。也就是说,冗余查找不到一微秒,因此除非代码每秒执行数百万次,否则对性能的影响不会很大。

一种避免冗余查找的简单方法(也适用于 ConcurrentMaps)是

linkedHashMap.merge(string, 1, Integer::sum);

如果有足够先进的 JIT 和足够简单的 get() 实现 - 以及它调用的 equals() - 它可能会在某个时候得到优化。但是没有任何保证。

get() 的实现细节很重要,因为它可能包括内存可见性影响(原子、锁)或具有超出编译器执行冗余代码消除能力的复杂性。

例如我猜 Collections.singletonMap 生成的地图很容易优化。但是 ConcurrentHashMap 当然不是因为它使用了 volatiles 和锁。

但最终确定性的唯一方法是查看所讨论方法的生成程序集,在它变得足够热以使其被调用者内联成为 JIT 之后。