Which passes arguments faster or uses a static variable in Java?

I have to use a variable that will never be changed in a method that will be often used in many threads. Which of these options is more effective?
Option 1:

public class Test { private static int myVar; public Test(int myVar){ this.myVar=myVar; } public void frequentlyUsedMultiThreadMethod(){ //read myVar } } 

Option 2:

 public class Test { public void frequentlyUsedMultiThreadMethod(int myVar){ //read myVar } } 

Option 3:

 public class Test { private final int myVar; public Test(int myVar){ this.myVar=myVar; } public void frequentlyUsedMultiThreadMethod(){ //read myVar } } 
+5
source share
4 answers

Reading a single int , no matter where it is, is so fast that it will be difficult for you to create a code fragment that demonstrates a significant time difference between the three approaches of your question, let alone find the difference in an arbitrary code fragment. The problem in constructing the reference is that the variable never changes, so the compiler will be allowed to read it once on a method call, even if frequentlyUsedMultiThreadMethod accesses it in a loop.

If so, the best approach is to consider which approach reflects the logical use of data in your program.

  • The first approach should be rejected, since several instances set the same static variable. This is confusing when the same value is used, and not true if multiple myVar values ​​are used for different instances.
  • The second approach requires the caller to pass the same variable several times, while the value is available at build time. While less confusing than the first approach, this approach is not ideal.
  • The third approach shows in the code that the value of myVar is one per instance and that it does not change. This is the most logical approach to the situation described in the question.
+8
source

The simplest, clearest, and least error prone solution is also the fastest (or fastest) that is often the case in Java.

Before you worry about speed, you should ask yourself; What is the easiest, clearest and least error prone approach? Passing values ​​through static values ​​is very error prone, for example when you have a multi-threaded application. Do not do this. Speed ​​doesn't matter if your program is down.

However, in this case, the static fields are also misleading. It is not clear to the user what they should install first. If you use recursion, it will make your work even harder.

Even worse, local variables can be optimized more than static fields. This means that static fields are also slower, possibly much slower.

Note: to prevent JIT optimizations, JMH uses a black hole for the resulting value to stop code optimization, using the static field for this.

Option 3 is perhaps best if the value never changes, for example, if you have multiple values, however, if the value changes, it will be slower, because you add overhead to create the Test object each time, the JIT may not be optimized .

+4
source

Option 2 could probably be a little better, as things can be pulled from the stack.

But: you should worry more about creating a good (aka SOLID ) design, and not worry about such subtleties.

it’s very difficult to understand what the JVM and the compiler will do right in time with your input in the very first place.

Meaning: You focus on creating good designs; you avoid blatant stupid mistakes; and that’s good enough for “thinking performance.” Everything else is premature optimization.

In other words: you have performance problems ... if you notice them. And then you will not guess which is better; you begin to profile your specific application to understand where the real bottlenecks are at runtime.

Of course, your question is interesting, "what happens at runtime"; but it really "doesn't matter" to guide your design decisions. They must be determined by the desire to create useful abstractions and a “model” that is truly suitable for your domain. Because this is what really matters!

Then you get code that other people can understand; and more importantly: it can be changed later when you find out what your real problems are!

0
source

How about this solution, uses less memory, not instantiated. you need some business in the method. The data will be stored on the thread stack and reduce thread context switching, which consumes extra time if you reuse threads such as ThreadPoolExecutor. If myVar can be changed for other use cases, it is best to add it as an argument to the method.

 public class Test { public static void frequentlyUsedMultiThreadMethod(int myVar){ //read myVar } } 
0
source