While reading Jack Shirazi's 'Java performance tuning', I came across the following statement:
"Instance and static variables can be up to an order of magnitude slower to operate on when
compared to method arguments and local variables."
Is this still applicable to Java 6/7? And if yes, what are the reasons behind it? (He explained something about having special bytecodes for accessing local variables/parameters but I did not understand it).
The key words here are can be. The issue is that locals and params (which are essentially a flavor of locals) may be in registers, while instance and static variables will ultimately end up in memory (they would get into registers for the time necessary to operate on them, but eventually back to the memory they go).
Even if access were 10 times slower, it would only matter if you were in a very long loop. And the Java Memory Model is pretty smart (sometime "too" smart) about optimizing memory access to instance variables. If you use an instance var in a long loop, say, to sum 100,000 doubles, the JVM is very likely to optimize that access and, in fact, not write the result to memory every single time. The exception being volatile fields. In fact, this whole optimization issue is why there are volatile fields.
Related
This question already has answers here:
java how expensive is a method call
(12 answers)
Closed 6 years ago.
I have a for loop which runs 4096 times and it should be as fast as possible. Performance is really important here. Currently I use getter methods inside the loop which just return values or objects from fields which don't change while the loop is in progress.
Example:
for (;;) {
doSomething(example.getValue());
}
Is there any overhead using getters? Is it faster using the following way?
Example:
Object object = example.getValue();
for (;;) {
doSomething(object);
}
If yes, is that also true for accessing public fields like example.value?
Edit: I don't use System.out.println() inside the loop.
Edit: Some fields are not final. No fields are volatile and no method (getter) is synchronized.
As Rogério answered, getting the object reference outside the loop (Object object = example.getValue();) will likely be faster (or will at least never be slower) than calling the getter inside the loop because
in the "worst" case, example.getValue() might actually do some very computationally-expensive stuff in the background despite that getter methods are supposed to be "trivial". By assigning a reference once and re-using it, you do this expensive computation only once.
in the "best" case, example.getValue() does something trivial such as return value; and so assigning it inside the loop would be no more expensive than outside the loop after the JIT compiler inlines the code.
However, more important is the difference in semantics between the two and its possible effects in a multi-threaded environment: If the state of the object example changes in a way which causes example.getValue() to return references to different objects, it is possible that, in each iteration, the method doSomething(Object object) will actually operate on a different instance of Object by directly calling doSomething(example.getValue());. On the other hand, by calling a getter outside the loop and setting a reference to the returned instance (Object object = example.getValue();), doSomething(object); will operate on object n times for n iterations.
This difference in semantics can cause behavior in a multi-threaded environment to be radically different from that in a single-threaded environment. Moreover, this need not be an actual "in-memory" multi-threading issue: If example.getValue() depends on e.g. database/HDD/network resources, it is possible that this data changes during execution of the loop, making it possible that a different object is returned even if the Java application itself is single-threaded. For this reason, it is best to consider what you actually want to accomplish with your loop and to then choose the option which best reflects the intended behavior.
It depends on the getter.
If it's a simple getter, the JIT will in-line it to a direct field access anyway, so there won't be a measurable difference. From a style point of view, use the getter - it's less code.
If the getter is accessing a volatile field, there's an extra memory access hit as the value can't be kept in the register, however the hit is very small.
If the getter is synchronized, then using a local variable will be measurably faster as locks don't need to be obtained and released every call, but the loop code will use the potentially stale value of the field at the time the getter was called.
You should prefer a local variable outside the loop, for the following reasons:
It tends to make the code easier to read/understand, by avoiding nested method calls like doSomething(example.getValue()) in a single line of code, and by allowing the code to give a better, more specific, name to the value returned by the getter method.
Not all getter methods are trivial (ie, they sometimes do some potentially expensive work), but developers often don't notice it, assuming a given method is trivial and inexpensive when it really isn't. In such cases, the code may take a significant performance hit without the developer realizing it. Extraction into a local variable tends to avoid this issue.
It's very easy to worry about performance much more than is necessary. I know the feeling. Some things to consider:
4096 is not much, so unless this has to complete in an extremely short time don't worry about performance so much.
If there is anything else remotely expensive going on in this loop, the getter won't matter.
Premature optimisation is the root of all evil. Focus on making your code correct and clear first. Then measure and profile it and narrow down the most expensive thing, and take care of that. Improve the actual algorithm if possible.
Regarding your question, I don't know exactly what the JIT does, but unless it can prove with certainty that example.getValue() or example.value doesn't change in the loop (which is hard to do unless the field is final and the getter is trivial) then there is logically no way it can avoid calling the getter repeatedly in the former sample since that would risk changing the behaviour of the program. The repeated calls are certainly some nonzero amount of extra work.
Having said all that, create the local variable outside the loop, whether or not it's faster, because it's clearer. Maybe that surprises you, but good code is not always the shortest. Expressing intent and other information is extremely important. In this case the local variable outside the loop makes it obvious to anyone reading the code that the argument to doSomething doesn't change (especially if you make it final) which is useful to know. Otherwise they might have to do some extra digging to make sure they know how the program behaves.
If you need to run it as fast as possible, you should not use System.out.println in critical sections.
Concerning getter: There is slight overhead for using getter, but you should not bother about it. Java does have getter and setter optimization in JIT compiler. So eventually they will be replaced by native code.
My rule is that in case of primitives, I can declare them static any time I want as they will not consume much memory. In practice, I usually use static primitives as project constants.
However, I saw many programmers declare objects as static as well. Obviously static object will increase memory consumption with each new static object.
For example, I often see that sharedpreference object is declared static so that any class can have updated information from it by calling apply() from anywhere in the code. I don't use it, but I create is as instance object instead and handle the login in a different manner.
So, how shall we be sure that we can safely declare some object as static? Do we try to predict its memory consumption or there is some other better method?
The reason for the question is the project that occupied 100MB or RAM on the mobile device. Static objects were used unnecessarily so a lot of data was kept in RAM without need. Once I converted static objects to instance objects, memory consumption dropped to 60MB.
PS. I have seen horrible cases of using static objects in the app just because programmers were lazy to properly handle the logic and such apps consumed up to 100% more memory than they should.
This
Obviously static object will increase memory consumption with each new static object.
is simply wrong: a static reference won't consume more or less memory than a non-static one.
Of course the static referenced object will stay in memory, as long as the class with the reference stays in memory, which might be until the end of the JVM.
On the other hand if every instance that needs A creates and holds an instance of A that will consume much more memory than a single A for everybody.
But memory consumption is really irrelevant in 99% of the cases, so I normally only think about it when I start having problems, or it becomes obvious I will get problems if I don't consider it.
More important are criteria like the following:
Will I ever want a different instance, for example for testing.
Does really everybody all the time need the same instance?
Might I want to use inheritance
When in doubt, don't use static
Regarding the updated question, which clarified that OP is asking about memory constraint devices
It sounds like someone is using static referenced Objects on a memory constraint device as some kind of cache, i.e. in order to avoid recreation of some object.
Based on that assumption the reasoning is somewhat different the result is more or less the same:
Don't cache stuff until you know you need it
If you cache something, make sure it helps you achieving your performance goal, by actually measuring
Make sure nothing else breaks, in this case especially memory constraints
If in doubt: don't cache
Finally: If you need a cache, use a cache, not some hacked solution like an abused static reference.
You have this completely back to front. It is instance variables that will use more memory, and it is static variables that need a strong motivation for making them static. If you don't already have a good reason for making them static, thy shouldn't be.
PS. I have seen horrible cases of using static objects in the app just because programmers were lazy to properly handle the logic and such apps consumed up to 100% more memory than they should.
Complete and utter nonsense. You have never seen any such thing. Using static variables doesn't double the memory, unless the class is never instantiated at all.
This article in the end mentions this: "With a lot of statically stored values, your application will not scale well".
I thought that initializing a variable only once and using it across instances is actually efficient as it saves reallocation of memory every time the class is initialized. It seems contradictory to the above statement. I understand that load time may increase as the JVM has to initialize these object at the very outset, but that would be just once.
Can anyone explain what this exactly means or what exactly "a lot" means in the statement?
It is referring to scaling developers, static variables is akin to the global value anti pattern, which can lead to code that is rigid, fragile and difficult to mock/unit test.
As far as CPU performance goes, static fields and methods are very fast because they do not encur the overheads associated with Object Orientated code and some performance/low latency specialists use them for exactly that reason.
Before I ask my question can I please ask not to get a lecture about optimising for no reason.
Consider the following questions purely academic.
I've been thinking about the efficiency of accesses between root (ie often used and often accessing each other) classes in Java, but this applies to most OO languages/compilers. The fastest way (I'm guessing) that you could access something in Java would be a static final reference. Theoretically, since that reference is available during loading, a good JIT compiler would remove the need to do any reference lookup to access the variable and point any accesses to that variable straight to a constant address. Perhaps for security reasons it doesn't work that way anyway, but bear with me...
Say I've decided that there are some order of operations problems or some arguments to pass at startup that means I can't have a static final reference, even if I were to go to the trouble of having each class construct the other as is recommended to get Java classes to have static final references to each other. Another reason I might not want to do this would be... oh, say, just for example, that I was providing platform specific implementations of some of these classes. ;-)
Now I'm left with two obvious choices. I can have my classes know about each other with a static reference (on some system hub class), which is set after constructing all classes (during which I mandate that they cannot access each other yet, thus doing away with order of operations problems at least during construction). On the other hand, the classes could have instance final references to each other, were I now to decide that sorting out the order of operations was important or could be made the responsibility of the person passing the args - or more to the point, providing platform specific implementations of these classes we want to have referencing each other.
A static variable means you don't have to look up the location of the variable wrt to the class it belongs to, saving you one operation. A final variable means you don't have to look up the value at all but it does have to belong to your class, so you save 'one operation'. OK I know I'm really handwaving now!
Then something else occurred to me: I could have static final stub classes, kind of like a wacky interface where each call was relegated to an 'impl' which can just extend the stub. The performance hit then would be the double function call required to run the functions and possibly I guess you can't declare your methods final anymore. I hypothesised that perhaps those could be inlined if they were appropriately declared, then gave up as I realised I would then have to think about whether or not the references to the 'impl's could be made static, or final, or...
So which of the three would turn out fastest? :-)
Any other thoughts on lowering frequent-access overheads or even other ways of hinting performance to the JIT compiler?
UPDATE: After running several hours of test of various things and reading http://www.ibm.com/developerworks/java/library/j-jtp02225.html I've found that most things you would normally look at when tuning e.g. C++ go out the window completely with the JIT compiler. I've seen it run 30 seconds of calculations once, twice, and on the third (and subsequent) runs decide "Hey, you aren't reading the result of that calculation, so I'm not running it!".
FWIW you can test data structures and I was able to develop an arraylist implementation that was more performant for my needs using a microbenchmark. The access patterns must have been random enough to keep the compiler guessing, but it still worked out how to better implement a generic-ified growing array with my simpler and more tuned code.
As far as the test here was concerned, I simply could not get a benchmark result! My simple test of calling a function and reading a variable from a final vs non-final object reference revealed more about the JIT than the JVM's access patterns. Unbelievably, calling the same function on the same object at different places in the method changes the time taken by a factor of FOUR!
As the guy in the IBM article says, the only way to test an optimisation is in-situ.
Thanks to everyone who pointed me along the way.
Its worth noting that static fields are stored in a special per-class object which contains the static fields for that class. Using static fields instead of object fields are unlikely to be any faster.
See the update, I answered my own question by doing some benchmarking, and found that there are far greater gains in unexpected areas and that performance for simple operations like referencing members is comparable on most modern systems where performance is limited more by memory bandwidth than CPU cycles.
Assuming you found a way to reliably profile your application, keep in mind that it will all go out the window should you switch to another jdk impl (IBM to Sun to OpenJDK etc), or even upgrade version on your existing JVM.
The reason you are having trouble, and would likely have different results with different JVM impls lies in the Java spec - is explicitly states that it does not define optimizations and leaves it to each implementation to optimize (or not) in any way so long as execution behavior is unchanged by the optimization.
I have some methods which allow me to lookup some identifiers, so essentially the run an SQL query and pass back a value.
Currently they are not static. Would it make sense to make them static, from a performance point of view i.e. have less in memory and save the time that is required to instantiate the object? Or are these considerations not really important.
There's no significant difference in practice, one way or another. It's especially true in your case, since SQL queries will take much more time than java method call.
As for memory usage, by making method static you're gonna gain 0 bytes of memory, that's absolutely certain.
A reason to use a static method is if you believe it improves clarity.
Being pedantic, using static could gain 8 bytes of memory (one reference) The value of this memory is about 10,000 th of one cent. Using a static call saves as much as 1 ns, an SQL query might take 10 ms, so the difference is 10,000,000 times or more.
In 99% of cases, using static will save you less than the cost over having to type the word (i.e. the value of your time to type the word is much greater than the memory/processing you will save) Use static if you believe it makes the program clearer. e.g. for writing utility methods.