Do the unused imports and unused objects in Java code create any performance impact?
Suppose an object is initialized and never used, what happens?
And what is the cost of unused imports?
Its a very common question.
Like most performance questions the best approach is to write the clearest and simplest code you can as this improves the maintainability of the code and helps ensure it performs reasonably well even after it is changed. (Clever/Obtuse/Needlessly Verbose code can run fast to start with but as it is changed by mere mortals it can get much slower)
Unused imports have a trivial impact on the compiler, but there are no imports in the byte code or at runtime.
Unused objects can be optimised away, but its best to avoid these as they almost always cause some performance impact, but more importantly make reading and maintaining your code more difficult.
Unused imports have no performance impact at runtime. It is purely a namespace mechanism. Nonetheless, you should always import only what you need for readability and avoid namespace collisions which are a nuisance.
Apart from code readability and hence maintainability of code, there may be faster compilation of java code (however, unnoticeable) by tidying up imports, but runtime performance is not impacted, since byte code generated is not impacted by untidy imports. Byte code generated remains the same.
While impact in compilation is minimal, the impact in deployment can be bad. I've just come across an unused import that required a separate library which became a maven dependency. A further transitive dependency problem was fortunately not found, but the .war file was thicker for no reason. Add to that a superfluous jar in the webapp classloader.
Though unused imports in Java file do not create any harm, it unnecessarily increases the length and size of the Java source file.
Yes it impact a bit on performance, if we are referring unused import statement in our java class. The Java compiler will check for references mentioned into the import statement and at minute level it impact on the performance of the your class.
Thanks
I think this being a common question is a consequence of the inherent problem of any programming language.
Syntax DOES NOT allow for a precise interpretation of what the machine is doing.
Any system is composed of 2 sides: the "real" and the "blueprint".
And it is extremely common to code in function of the "abstract"/"blueprint".
import Database;
class MyPojo {
int intField;
public static class Manager {
final MyPojo instance;
public Manager(Database db) {
instance = db.getMyPojo();
}
}
}
This will allow to easily find any MyPojo related functionality.
So I don't know how academia defines a distinction between both but, anything "real", involves memory allocation, reference/pointer manipulation, race conditions... etc...
These two perspectives of a system are completely different, yet the two of them are expressed in the same syntactical 2-dimensional plane... Words.
And it is not fair to either of them, a blueprint in architecture requires 2 dimensions, but the real must be handled on site.
The same way it becomes increasingly difficult to handle complex systems with just a 2 dimensional syntax, that even if IDE's try to help us with hyperlinks, it becomes an issue that could be handled easily in a 3 dimensional plane.
I believe the problem relies in how the language evolved from a pure OOP paradigm to a functional reactive one, where immutability now allows the defining of "nuclear" datatypes... Maybe all we always needed were arrays[]...
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
When should one use final?
I tend to declare all variables final unless necessary. I consider this to be a good practice because it allows the compiler to check that the identifier is used as I expect (e.g. it is not mutated). On the other hand it clutters up the code, and perhaps this is not "the Java way".
I am wondering if there is a generally accepted best practice regarding the non-required use of final variables, and if there are other tradeoffs or aspects to this discussion that should be made aware of.
The "Java way" is inherently, intrinsically cluttery.
I say it's a good practice, but not one I follow.
Tests generally ensure I'm doing what I intend, and it's too cluttery for my aesthetics.
Some projects routinely apply final to all effectively final local variables. I personally find reading such code much easier, due to the lessened cognitive load. A non-final variable could be reassigned anywhere, and it's especially problematic in code with multiple levels of nested ifs and fors. You never know what code path may have reassigned it.
As for the concern of code clutter, when applied to local variables I don't find it damaging—in fact it makes me spot all declarations more easily due to syntax coloring.
Unfortunately, when final is used on parameters, catch blocks, enhanced-for loops and all other places except local variables in the narrow sense, the code does tend to become cluttered. This is quite unfortunate because a reassignment in these cases is even more confusing and they should really have been final by default.
There are code linting tools that will flag the reassignment of these variables, and that helps.
I consider it good practice, more for maintenance programmers (including me!) than for the compiler. It's easier to think about a method if I don't need to worry about which variables might be changing inside it.
Yes, it's a very good idea, because it clearly shows what fields must be provided at object construction.
I strongly disagree that it creates "code clutter"; it's a good and powerful aspect of the language.
As a design principle, you should make your classes immutable (all final fields) if you can, because they may be safely published (ie freely passed around without fear they will be corrupted). Although note that the fields themselves need to be immutable objects too.
It definitely gives you a better code, easy to see which all variables are going to be changed.
It also informs the compiler that it is not going to change which can result to better optimization.
Along side it allows your IDE to give you compile time notification if you tend to do any mistake.
Some good analysis tools, like PMD, advices to put always final unless necessary. So the convention in that tools says it's a good practice
But I think that so many final tokens in code may get it less human-friendly.
I would say yes, not so much for the compiler optimisation, but rather for readibility.
But personally I don't use it. Java is quite verbose by itself, and if we followed everything considered "good practice", the code would be unredable from all the boilerplate. It's a matter of preference, though.
You pretty much summed up the pros and cons...
I can just add another con:
the reader of the code need not to reason at all about the value of a final variable (except for rare bad-code cases).
So, yes, it's a good practice.
And the clutter isn't that bad, after you get used to it (like unix :-P). Plus, typical IDEs do it automatically for ya...
Take the following code snap for example:
public int demoMethod(){
SomeClass object= getItFromSomewhere();
return object.getResult();
}
also we can directly return getItFromSomewhere().getResult(). My question is whether the definition of "object" will low down the performance? And in some case, maybe the temporary local variable is very complicated, such as
SomeClass object = otherClassObject.getMethod1().getMethod2().getMethod3().getMethod4();
return object.getMethod5();
If I don't use the temporary "object", the statement will be very difficult to read, how about you guys deal with this case?
Afaik will be completely removed by jit. So there should not be any impact on performance introducing additional local variables to simplify expressions.
PS: The long expression, a.d.b.c is called a 'train wreck' by uncle bob. They are hard to read and a PITA to debug when you get an exception like a NPE.
As a general rule (in my opinion, but I trust I am not alone), your code should be optimized for readability before any other kind of optimization. This will allow other programmers to improve it later on, if needed. A very fast but unreadable code quickly becomes useless as nobody is able to make changes to it. Also, trust the compilers (javac and the JIT): they know how to rewrite your code to remove unused statements, like a variable that is not actually necessary.
Then, if speed is an issue, you should try to improve it by choosing more appropriate data structures (especially containers) and algorithms.
Lastly, if speed is still an issue (very rare nowadays), you should seek the advice of a specialist. There are people who do wonders with code that is seemingly efficient to begin with, but this is not something the average developer should do on a daily basis.
Got to know that we can initialize a collection in java by using double brace initialization. And did some search on that and found that it is not advised to use it because of its performance issue.
private static final Set<String> VALID_CODES = new HashSet<String>() {{
add("XZ13s");
add("AB21/X");
add("YYLEX");
add("AR2D");
}};
Just want to know, is there any positive side or advantage of DOUBLE BRACE INITIALIZATION??
not advised to use it because of its performance issue.
I don't see any performance issue. Whenever you see someone say I did/didn't do something for performance reason you should expect to see detailed analysis comparing the alternatives explaining how one met the specific required performance and the other did not. If you don't see all this you might assume the author is just guessing.
EDIT: While I will concede each class takes a small amount of time to load, the running performance is exactly the same. I have demonstrated here https://stackoverflow.com/a/14627268/57695
I would use double brace notation if you believe it's simpler and clearer.
A disadvantage is that your are changing the type of the collection which can confuse functions where that is not expected. e.g. equals.
Note: As Lukas Eder points out, you want to be careful if you do this in a non-static context. The anonymous sub-class collection will implicitly have a reference to the outer instance and if it lives longer than the collection, this would be a memory leak. Have you ever thought of the possibility of a memory leak?
There's no particular performance issue (beyond the cost of loading a class via the classloader - negligible)
The above does create an anonymous class and as such it contains an implicit this reference to the surrounding instance. That can cause some confusion for serialisation frameworks. e.g. you serialise the anonymous class you've created, and you suddenly find you're also trying to serialise the containing instance.
I would highlight that anonymous classes can be used a lot under the covers in different frameworks and indeed languages (Scala - I'm looking at you). I've never heard anyone suggest that Scala has issues with performance due to classloading. Initial startup may be fractionally slower, but bear in mind JVM startup, JIT warmup, any network access etc.
You might argue that your application footprint is bigger, due to more classes. I suspect (again) the effect is negligible (unless you construct a whole application out of anonymous classes!)
Guava's ImmutableList has a series of overloaded of() methods. As discussed in the context of this solved question, these exist to avoid the warnings that occur when mixing varargs with generics.
But in addition to that, the 0 and 1 parameter methods each rely on a specialized list implementation. It would seem that the same thing could be done for the 2..11 parameter methods, thereby reducing memory consumption of these lists - along the lines of
final class ImmutableListWith2Elements<E> extends ImmutableList<E> {
final E e1;
final E e2;
...
Instead, they use an array-based implementation, which means storing an array object and a reference to the array in addition to the content references. Can you help me understand the trade-offs involved here?
Can you help me understand the trade-offs involved here?
It is a tradeoff between:
Performance - there is a saving from not allocating the temporary array. However, one would need to do some extensive code analysis and benchmarking to quantify that saving. (I suspect that in most applications it would be insignificant. And read this link contributed by #Voo!)
Readability - having a bunch of the extra overloads clutters up the javadocs.
Maintainability - having a bunch of overloads that are implemented iun such a way that the temporary object is not required would entail a lot of copy/paste programming, and this makes future code maintenance harder.
Utility - how often would these overloads be used? I expect that the answer would be "rarely".
Bytecode footprint - these extra overloads would contribute to application bloat for every application using the Guava JAR file.
My advice:
Don't bug the Guava developers about this. They've already made up their minds about the tradeoffs. You'll just be wasting your breath.
If the lack of these classes or methods hurts your application, roll your own additions. (But try to do it in a way that doesn't involve a private "fork" of Guava ... because you'll probably regret that in the long term.)
For the record, I think that the Guava developers got this right.
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.