I have to use a variable which will never be changed in method which will be frequently used in many threads. Which of these variants are more efficient?
Variant 1:
public class Test {
private static int myVar;
public Test(int myVar){
this.myVar=myVar;
}
public void frequentlyUsedMultiThreadMethod(){
//read myVar
}
}
Variant 2:
public class Test {
public void frequentlyUsedMultiThreadMethod(int myVar){
//read myVar
}
}
Variant 3:
public class Test {
private final int myVar;
public Test(int myVar){
this.myVar=myVar;
}
public void frequentlyUsedMultiThreadMethod(){
//read myVar
}
}
Static variables are generally considered bad because they represent global state and are therefore much more difficult to reason about. In particular, they break the assumptions of object-oriented programming.
As expected, virtual method calls are the slowest, non-virtual method calls are faster, and static method calls are even faster.
Using static variables may make a function a tiny bit faster. However, this will cause problems if you ever want to make your program multi-threaded. Since static variables are shared between function invocations, invoking the function simultaneously in different threads will result in undefined behaviour.
Accessing a static field of another class is about 4x slower than accessing any field in the same class or superclass.
Reading a single int
, no matter from what location, is so extremely fast, that you would be hard-pressed to construct a piece of code that demonstrates a meaningful difference in time between the three approaches from your question, let alone finding a difference in arbitrary piece of code. The problem in constructing a benchmark is that the variable never changes, so the compiler would be allowed to read it once per method call, even if frequentlyUsedMultiThreadMethod
accesses it in a loop.
When this is the case, the best approach is to think what approach reflects the logical use of the data in your program.
myVar
are used for different instances.myVar
is one per instance, and that it does not change. This is the most logical approach to the situation that you described in the question.The simplest, clearest and least error prone solution is also the fastest (or fast enough) which is often the case in Java.
Before you worry about speed, you should ask yourself; what is the simplest, clearest and least error prone approach? Passing values via static values is very error prone, esp when you have a multi-threaded application. Don't do it. The speed is unimportant if your program doesn't work.
However, in this case it is also confusing to use static
fields. It is not clear to the caller what they must set first. If you use recursion, this will make your job even harder.
To make matters worse, local variables can be optimised more than static fields. This means static fields are also slower, possibly much slower.
Note: to prevent JIT optimisations JMH uses a "blackhole" for the resulting value to stop code being optimised away, it uses a static
field to do it.
Option 3 is perhaps best provided the value never changes, esp if you have multiple values, however if the value does change it will be slower as you are adding overhead to create the Test
object each time, the JIT might not optimise away.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With