[英]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.