In front of a long loop, it costs more (processor memory) to assign redundantly the same value, or to check before the assignment?
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
}
}
VS.
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;
}
}
}
And would it cost the same if count
would be present in a different object (injected as a singleton in a Spring context) and the increments/check/reset would be like:
config.incrementCount();
config.getCount();
config.resetCount();
CodePudding user response:
The short answer to your question is it doesn't matter. Either approach will have roughly same performance and most probably will be dominated by doLogic
.
Your first choice should always be to write simple and idiomatic code instead of doing premature optimization.
The long answer is it depends (it always does, doesn't it?).
First of all, you don't really know what kind of optimizations JIT will do to your code. What is true for one platform and Java version may not be true for another. You can't rely on anything that is not explicitly guaranteed.
Second, you know what they say about premature optimization. It's always a good idea to benchmark and profile your code, but even benchmarks are not 100% reliable.
Ok, let's benchmark:
# 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
While for the case with simple counter variable the "if optimization" seems to lose, in the second case the difference is within the margin of error.
In my benchmark I just used a simple static field holding Counter
class. Looking at the ASM, generated by JIT, it appears that method calls were inlined. Your situation may be different, as enterprise java and Spring are infamous for doing obscure magic behind the scenes (e.g. via proxies and bytecode manipulation). Not only methods may not be inlined, but also some hidden overheads may emerge unexpectedly.
P.S. If you are interested in performance and microoptimization for JVM, I suggest to read Alexey Shipilev's JVM Anatomy Quarks Series.