[英]Java Performance: regarding using Long.valueOf(..)
我們經常使用Long.valueOf()進行相同的字段轉換。 所以這沒關系,或者我們需要將轉換的值存儲在其他字段中然后使用。 示例:我們在 String 中接收特定的 id,無論我們在哪里使用,我們每次都執行 Long.valueOf(id)。
喜歡 :
void methodName(String id) {
//some code
... = Long.valueOf(id);
....
....
callOtherMethod(Long.valueOf(id));
....
...
map.put("urId", Long.valueOf(id));
....
}
當我們考慮性能和所有這些時,這可以嗎? 別的
這個很好去
喜歡 :
void methodName(String id) {
//some code
Long longId = Long.valueOf(id);
... = longId;
....
....
callOtherMethod(longId);
....
...
map.put("urId", longId);
....
}
哪一個最好,為什么(如果你能解釋一下)?
我個人贊成不要多次重復相同的操作。 所以我更喜歡你的第二種方法。
在編程時,多次編寫的同一段代碼通常是難聞的,如果您可以提取重復的代碼段以供重用,例如將重復的塊提取到參數化方法中,或者在這種情況下分配Long.valueOf(id)
的輸出Long.valueOf(id)
到一個變量,您可以避免變得難以閱讀的冗長代碼。
如果您從Long.valueOf()
(或任何其他方法)返回的值應該Long.valueOf()
使用,則使用第二種方法總是更好。 因為在本地存儲它總是比再次計算更便宜。
對於有問題的示例,不難計算與 JMH 的性能差異。 我創建了可以計算這個的小基准:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5)
@Measurement(iterations = 10)
@Fork(1)
@State(Scope.Thread)
public class ValueOfPerfTest {
@Param({ "1000" })
private String number;
@Param({ "10", "20", "30"})
private long tokens;
@Benchmark
public void cachedValueOf(Blackhole blackhole) {
Long l = Long.valueOf(number);
// three times using the consume
blackhole.consume(l);
blackhole.consume(l);
blackhole.consume(l);
Blackhole.consumeCPU(tokens);
}
@Benchmark
public void nonCachedValueOf(Blackhole blackhole) {
// three times using the consume
blackhole.consume(Long.valueOf(number));
blackhole.consume(Long.valueOf(number));
blackhole.consume(Long.valueOf(number));
Blackhole.consumeCPU(tokens);
}
@Benchmark
public Long valueOf(Blackhole blackhole) {
Blackhole.consumeCPU(tokens);
return Long.valueOf(number);
}
@Benchmark
public void baseline(){
Blackhole.consumeCPU(tokens);
}
}
我不想在這里詳細說明 JMH,但主要區別在於nonCachedValueOf
調用了Long.valueOf()
3 倍,而在緩存版本中只調用了 1 次。 我的期望是非緩存版本會慢 3 倍,這基本上是結果顯示的內容:
[java] Benchmark (number) (tokens) Mode Samples Score Error Units
[java] i.n.a.p.ValueOfPerfTest.baseline 1000 10 avgt 10 11.238 ± 0.387 ns/op
[java] i.n.a.p.ValueOfPerfTest.baseline 1000 20 avgt 10 30.392 ± 0.668 ns/op
[java] i.n.a.p.ValueOfPerfTest.baseline 1000 30 avgt 10 50.217 ± 1.101 ns/op
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 1000 10 avgt 10 37.368 ± 2.035 ns/op
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 1000 20 avgt 10 54.614 ± 3.847 ns/op
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 1000 30 avgt 10 74.412 ± 2.474 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 1000 10 avgt 10 82.329 ± 2.649 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 1000 20 avgt 10 100.595 ± 2.476 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 1000 30 avgt 10 118.715 ± 3.277 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 1000 10 avgt 10 35.815 ± 0.766 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 1000 20 avgt 10 53.074 ± 3.942 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 1000 30 avgt 10 73.378 ± 2.318 ns/op
如果您對結果進行更深入的挖掘,如果您排除基線(這里有 30 個標記),您會得到大約以下結果:
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 24,195 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 68,498 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 23,161 ns/op
很明顯,幾乎慢了 3 倍。
關於每次使用 Long.valueOf 創建任何新對象的問題? , 如果數字不在緩存中,答案是肯定的。 java 有“常用值”的緩存,默認情況下,從 -128 到 127 的數字都有緩存。但可以通過使用-XX:AutoBoxCacheMax
來增加-XX:AutoBoxCacheMax
JVM 選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.