Java performance: true vs. Boolean.TRUE
Asked Answered
S

9

36

Which of the following is better in terms of performance and efficient memory usage?

Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

boolean isItTrue(arg){
    return Boolean.TRUE
}

Boolean isItTrue(arg){
    return true;
}

boolean isItTrue(arg){
    return true;
}

It should be faster and easier to work with primitive types, but on the other hand, when using a reference to a static object, no new value is created. Or is it optimized on compiler level and all true and false are replaced by references to the static objects to save memory?

Silsbye answered 2/8, 2011 at 11:49 Comment(2)
probably a micro-optimization. what context is it called in?Heeler
Possibly can help this threadBulk
D
33

Firstly, the performance advantage of using any one over the others is most likely to be too small to be relevant1. Code simplicity / readability / maintainability is a far more important ... in the vast majority of cases.

Or is it optimized on compiler level and all true and false are replaced by references to the static objects to save memory?

There's a fundamental misunderstanding here. The boolean type is a primitive (not reference) type. The true and false values cannot be replaced with references. Furthermore, the space used to hold representations of true and false depends on the context. It is often a single byte ... which is significantly less than the 8 bytes needed to store a reference on a 64-bit JVM (with oops compression disabled). So that "optimization" would NOT save memory even if it was technically possible.


None of your examples involve creation of Boolean instances2 so we can discount that from our performance analysis.


# Example 1
boolean isItTrue(arg){
    return true;
}

This one will be equal to or faster than all of the others because it simply entails setting a register to zero.


# Example 2
Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

Taken in isolation, this has to load a static reference from memory, rather than zero a register. However, the JIT compiler may be able to optimize this away in some circumstances.


# Example 3
Boolean isItTrue(arg){
    return true;
}

On the face of it, this involve a call to Boolean.valueOf(true) to "box" the true, but the JIT compiler should be able to optimize it to the same code as the previous one by inlining the call.


# Example 4
boolean isItTrue(arg){
    return Boolean.TRUE
}

On the face of it, this involves a call to Boolean.booleanValue(Boolean.TRUE) to "unbox" the Boolean. This call can be inlined. It is also possible that the JIT compiler can avoid loading the reference to the Boolean object and fetching its value field.


In summary, the relative performance of your 4 examples depends on how successful the JIT compiler is in optimizing. That will depend on the context, the specifics of the JIT compiler, the JVM settings, and so on. In theory, the JIT compiler could produce the same (optimal) code for all of them. In practice, the difference will be insignificant in nearly all cases. (And this is not a practical example anyway.)


1 - This benchmark unwittingly demonstrates this. If the results it presents are to be believed, then the performance difference between the best and worst versions is less than 1 ns per call.
2 - It is theoretically possible that 3 of the 4 could trigger the initialization of the Boolean class AND that your application wouldn't otherwise have done that. In that highly unlikely event, your entire application will allocate 2 objects that wouldn't otherwise have been allocated. The initialization will probably take a few microseconds, and consume a few bytes of RAM (less than 50) in the long term. This is irrelevant in practice.

Dvina answered 2/8, 2011 at 12:11 Comment(0)
G
13

If there is any performance gain it is so minuscule as to be irrelevant. Boolean.TRUE and Boolean.FALSE don't return a new object in any case.

Gottschalk answered 2/8, 2011 at 11:52 Comment(0)
C
12

Favour clarity for the code maintainer over such micro-optimisations. The question should not be "which is smaller/faster", first which expresses what you mean.

If the method returns a Boolean object then whoever receives needs to decide whether there is a possibility that it might be null, and that if it is null that it might mean something different from true/false, like "we don't know".

So return type of boolean, if that is what you mean, otherwise, if you want to allow Null, then Boolean.

If returning a boolean then

return true; // or false

must be better than relying on autoboxing, again for the sake of clarity as well as performance.

If returning Boolean then

return Boolean.TRUE

must be good, it just avoids creating extra garbage, much as I oppose micro-optimisation I see no value in being wilfully inefficient. I'd argue that it's also clearer in that you are conspicuously matching the return type.

Celebrate answered 2/8, 2011 at 11:58 Comment(0)
H
7

They will be much faster. I don't think there will be any difference between these two.

Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

boolean isItTrue(arg){
    return true;
}

But other implementation will be slower because it will be boxing and unboxing on the back end with will take some time of processor.


Edit

I have collected some facts by implementing the 4 different ways. Just want to share it with you, I don't if its the write way to do that.

Boolean isItTrue(){ 
    return Boolean.TRUE;
}

Free Memory before start --> 16030936
Time taken in Secs --> 7.844
Free Memory After Process --> 15940472
Memory Usage --> 90464

boolean isItTrue(){
    return Boolean.TRUE;
}

Free Memory before start --> 16030936
Time taken in Secs --> 10.109
Free Memory After Process --> 15940472
Memory Usage --> 90464

Boolean isItTrue(){
    return true;
}

Free Memory before start --> 16030936
Time taken in Secs --> 7.906
Free Memory After Process --> 15940472
Memory Usage --> 90464

boolean isItTrue(){
    return true;
}

Free Memory before start --> 16030936
Time taken in Secs --> 7.828
Free Memory After Process --> 15940472
Memory Usage --> 90464

Main Class

public static void main(String[] args){
    NewClass n = new NewClass();

    long sysTime = System.currentTimeMillis();

    Runtime rt = Runtime.getRuntime();
    long freeMem = rt.freeMemory();
    System.out.println( "Free Memory before start --> " + freeMem );
    for( int i = 0; i < Integer.MAX_VALUE; i++ ){
        n.isItTrue();
    }
    System.out.println( "Time taken in Secs --> " + (System.currentTimeMillis() - sysTime)/1000D);
    System.out.println( "Free Memory After Process --> " + rt.freeMemory() );
    System.out.println( "Memory Usage --> " + ( freeMem - rt.freeMemory() ) );
}
Hoofbound answered 2/8, 2011 at 11:54 Comment(4)
I do not think your claim that "They will be much faster" is correct. Any performance difference would be minute.Resigned
Hay, I have added some facts after implementing it. Take a look.Hoofbound
Micro-benchamarks are notoriously difficult to write properly (hence the usual advice is to profile your real application). Have a look at ibm.com/developerworks/java/library/j-jtp02225/index.html and wikis.sun.com/display/HotSpotInternals/MicroBenchmarksResigned
This benchmark has flaws that could render the results invalid. Even if the numbers were valid, they are not representative of how the method is likely to be used, and hence of the context in which the JIT compiler would optimize them. Finally, the best-to-worst delta is 2.3 seconds for 2^31 calls == less than a nano-second == 2 or 3 CPU clock ticks on stock hardware. If that is representative, it is clearly down at the level where it will have minimal impact on the performance of a typical application.Dvina
G
4

The last one

boolean isItTrue(arg){
    return true;
}

I use Boolean only if the method needs sometimes to return null

Galloping answered 2/8, 2011 at 11:52 Comment(0)
P
3

My rules of thumb are as follows:

  1. The default choice is the primitive type (boolean).
  2. If I need nullability or need to store the values in a container, I use the class (Boolean).

With this in mind, my default choice would be:

boolean isItTrue(arg){
    return true;
}

As far as performance is concerned, the only thing that seems certain is that it's hard to imagine a scenario where using Boolean would be faster than using boolean. Whether it would be slower or the same depends on a lot of things and it's impossible to answer in general.

If you really care about this, profile the code where it matters!

Polyester answered 2/8, 2011 at 11:53 Comment(0)
P
2

By that logic, the reference to the static object itself is as costly as the truth value, if not more.

Using objects may be somewhat slower than primitives, but I wouldn't worry: the difference is irrelevant.

Pirn answered 2/8, 2011 at 11:53 Comment(0)
Z
2

Use the last one (just boolean). Even if the compiler optimizes them all to the same thing, at the very least you're making the compiler's job easier (it's not an easy job you know!).

Plus it's fewer keystrokes (don't need to press shift). But really, the only reason you should use the wrapper class is when you need the ability to set it to null, and for use in generic data structures like LinkedList<E>.

Zed answered 2/8, 2011 at 11:56 Comment(0)
J
0

java.lang.Boolean takes 16 bytes.

this is the way to go if you are only looking for performance and memory size issues:

boolean isItTrue(arg){
    return true;
}
Jan answered 2/8, 2011 at 11:53 Comment(4)
You won't save any space, because the Boolean.TRUE and Boolean.FALSE objects will be created anyway if your program causes the Boolean class to be initialized.Dvina
Will it inititalize a Boolean in the background? I was under the impression that it didn't.Rothrock
Not in the background. But the JVM spec says that the initialization will occur if any static is used, any static method is called or any object instance is created (and other things). If any of those occur, the TRUE and FALSE instances will be created and the space will be used ... whether or not your application uses the instances.Dvina
Boolean.TRUE is a static field and is reused across all trues autoboxed to a BooleanSuave

© 2022 - 2024 — McMap. All rights reserved.