簡體   English   中英

Java 中的冗余分配與分配前檢查

[英]Redundant assignment vs check before assignment in Java

在長循環前,冗余分配相同的值,還是分配前檢查成本更高(處理器+內存)?

int count = 0;
for(int i=0; i<100_000; i++){
    if (...) {
        count++
        doLogic(count); // logic is strictly related with count
    } else {
      count = 0;  //50.000 redundant assignment
    }
}

對比。

int count = 0;
for(int i=0; i<10_000; i++){
    if (...) {
        count++
        doLogic(count); // logic is strictly related with count
    } else {
        if(count > 0) { // 50.000 checks 
          count = 0;
        }
    }
}

如果count存在於不同的對象中(在 Spring 上下文中作為單例注入)並且增量/檢查/重置將像這樣,它的成本是否相同:

config.incrementCount();
config.getCount();
config.resetCount();

對你的問題的簡短回答是沒關系 兩種方法都具有大致相同的性能,並且很可能由doLogic主導。

您的首選應該始終是編寫簡單且符合地道的代碼,而不是過早地進行優化。


答案很長,這取決於(它總是如此,不是嗎?)。

首先,您並不真正知道JIT會對您的代碼進行什么樣的優化。 對一個平台和 Java 版本適用的情況可能不適用於另一種平台和 Java 版本。 你不能依賴任何沒有明確保證的東西。

其次,您知道他們對過早優化的看法。 對代碼進行基准測試和概要分析總是一個好主意,但即使是基准測試也不是 100% 可靠的。

好的,讓我們進行基准測試:

# First case, variable counter
Benchmark                 Mode  Cnt  Score   Error  Units
Benchmark1.testCounter    avgt    8  0.149 ± 0.026  ms/op
Benchmark1.testCounterIf  avgt    8  0.190 ± 0.036  ms/op

# Second case, counter in the wrapper class
Benchmark                      Mode  Cnt  Score   Error  Units
Benchmark1.testCounterClass    avgt    8  0.198 ± 0.025  ms/op
Benchmark1.testCounterClassIf  avgt    8  0.181 ± 0.016  ms/op

基准代碼

雖然對於簡單計數器變量的情況,“如果優化”似乎失敗了,但在第二種情況下,差異在誤差范圍內。

在我的基准測試中,我只使用了一個包含Counter類的簡單靜態字段。 查看由 JIT 生成的 ASM,方法調用似乎是內聯的。 您的情況可能有所不同,因為企業 Java 和 Spring 因在幕后(例如通過代理和字節碼操作)執行晦澀的魔法而臭名昭著。 不僅方法可能不會被內聯,而且一些隱藏的開銷可能會意外出現。


PS 如果您對 JVM 的性能和微優化感興趣,我建議您閱讀Alexey Shipilev 的 JVM Anatomy Quarks 系列

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM