Java性能:关于使用Long.valueOf(…)
我们经常使用Long.valueOf()来进行相同的场浇铸。所以这是可以的,或者我们需要将浇铸值存储在其他字段中,然后使用。 例子: 我们在字符串中接收特定的id,无论在哪里使用,我们每次都执行Long.valueOf(id) 比如:Java性能:关于使用Long.valueOf(…),java,performance,casting,Java,Performance,Casting,我们经常使用Long.valueOf()来进行相同的场浇铸。所以这是可以的,或者我们需要将浇铸值存储在其他字段中,然后使用。 例子: 我们在字符串中接收特定的id,无论在哪里使用,我们每次都执行Long.valueOf(id) 比如: void methodName(String id) { //some code ... = Long.valueOf(id); .... .... callOtherMethod(Long.valueOf(id)); .... ... map.put("urId
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);
....
}
这是好的,我们考虑性能和所有这些。否则
这个可以走了
比如:
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()
(或任何其他方法)返回的值应该被多次使用,则最好使用第二种方法。因为存储在本地也比再次计算便宜
对于所讨论的示例,使用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倍,而在缓存版本中只有一次。我的预期是,非缓存版本将慢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个标记),您将得到大约以下结果:
非常清楚,几乎是第三因子
关于您每次使用Long.valueOf创建任何新对象时的问题,如果该数字不在缓存中,则答案为“是”。。java具有“常用值”的缓存,默认情况下,该缓存用于-128到127之间的数字。但是可以通过使用-XX:AutoBoxCacheMax
JVM选项来增加它。第二种方法是最好的,因为您可以避免函数调用的值(…)
是否存在需要修复的性能问题?否则,您应该总是选择可读性最好的代码,这是一个品味和/或项目规则的问题。我更喜欢第二种方法。还要注意,这不是性能问题。在选择一个对象而不是另一个对象时,您不太可能看到可测量的差异。@Kayaman每次都使用Long.valueOf创建任何新对象(如字符串中的对象)以进行强制转换或不转换?。你能解释第二种方法在哪方面是有益的吗