Monday, March 09, 2009

JavaFX's memory overhead, some (high) numbers

Lately I took a look at the TweetBox Twitter client which is build with JavaFX(© 2008-2009 Sun Microsystems). I thought it would be fun to check whether a Java based Twitter client would have less memory usage problems than those popular Adobe Air(© Adobe) based clients, such as Tweetdeck. If you search for memory leak in Twitter you will get a lot of references about Tweetdeck, which might only be caused by it's a popularity. Because JavaFX is JVM based it actually has an advantage in the area of memory usage analysis over Adobe Air.


TweetBox currently does not perform very well, but the author is working on improving it and I also tried to help him out a little bit.

When looking for memory usage using my favorite tool I was quite surprised to see the high overhead of variables in JavaFX.

Let's have a look at some numbers for the shallow size of variables (32 bit CPU):

Shallow Size

Boolean:
24 bytes (Yes, this is for one bit of information)
Integer: 24 bytes
Objects: 24 bytes
Floats: 24 bytes
Sequence: 32 bytes(never smaller than 48 bytes)


JavaFX objects seems to have a relatively large number of fields, so this overhead might be really become significant, also as always, it depends on your application. For comparsion a boolean in Java takes 1 byte and Objects have a general overhead of 8 bytes (SUN 32 bit JVM). [updated] Note that even a Boolean object in Java would in practice only require 4 Bytes for the Reference, because only 2 of them (for true and false) are needed.
An idea could be to have a native BitSet in JavaFX, which would only need one bit for each boolean value (plus a fixed overhead).

For details about the memory usage of Java objects check my post here.

But when looking at the retained size it even gets worse. Due to JavaFX's fancy binding mechanism those objects often reference other objects which causes the retained size to "explode".


Average "Retained size"

Boolean:
111 bytes

Integer: 53 bytes

Objects: 76 bytes

Floats: 53 bytes

Sequence: 84 bytes

111 bytes average (!) for a Boolean is absurdly high and I'm not sure yet whether that's because Tweetbox using it in the wrong way or because of a bug. It is caused by long chain's of com.sun.javafx.runtime.location.DynamicDependentLocation.
I have no clue what that is and even Google doesn't seem to know.

I hope JavaFX's memory usage will improve over time. Right know you have to be very careful to not run into memory usage problems.
Note that other dynamic languages on the Java stack also currently have a higher memory overhead than Java, because most of them can't directly map to the Java object model.

I assume that the footprint of JavaFX Mobile is similiar.
IMHO Googles decision to go for plain Java on it's Android platform was a smart decision



[update]: Michael Heinrichs just blogged about the difference between "def" and "var" in JavaFX Mobile.  It seems to me that "def" could help to optimize memory usage. 




11 comments:

Anonymous said...

interesting entry. but i am not sure if its fair to compare a boolean primitive in java with a Boolean used in javafx which can trigger events or sync with other objects or even be part of a formula, only (partial) evaluated when values change.

In other words it is likely that a Boolean in JavaFX is used differently because of its capabilities.

anyway, i would file a bug and see what happens ;)
http://javafx-jira.kenai.com/

subscribed to your rss feed

Unknown said...

Hi Michael,
Yes I agree it's not really fair to compare the primitive against an object. But on the other side, if you can't choose in JavaFX, what can you do?
Still the Boolean Object in Java would in most cases only require around 4 bytes (If I put them into a collection) in average because there are only 2 of them needed, which can be reused.

Yes the binding costs memory, but why do I have to pay for it, if I don't use it?

Couldn't the compiler optimize that?

Unknown said...

Just wondering, where the numbers above taken after garbage collection? Bindings are implemented with weak references, looking at a snapshot can give a wrong impression.

AFAIK the additional footprint of an unused binding is only a single reference, there is not much the compiler can optimize about that.

Unknown said...

Hi Michael,
as fas as I remember I did GC's before the heap dump.

As far as I know the heap dump also causes a full GC to be run, which should usually be enought to reclaim objects which are only weakly referenced.
The references to the
DynamicDependentLocation instances were strong.

Maybe I should file a bug for that ...

Unknown said...

Yes, please file a bug. 111 bytes for an instance variable is definitely not the expected behavior.

Unknown said...

Hi Michael,
Actually it's 111 bytes average. Some of the Booleans consume around 3kbyte as far as I remember.

Unknown said...

Hi Markus,

Nice post. I am really flabbergasted by these numbers, although I did notice how soon TweetBox reaches 100M in memory.

I think you should definitely file your findings as a bug at javafx. They will appreciate it.

Anonymous said...

What you are looking at is not the size of the data, what you are looking at is the relationship graph for an object. A Boolean instance variable in JavaFX will take two bytes, if the variable is private to the script and does not have dynamic dependencies.

A JavaFX variable which fires off a complex chain of behavior through binding and/or on-replace triggers will have a commensurate data-structure representing those dynamic dependencies.

JavaFX is in very active development, reducing footprint is a priority, and each release has/will make dramatic improvements in footprint.

Unknown said...

Hi Robert,
Well, I looked at the overhead of "var" and that is clearly 24 bytes in most cases compared, which is already 3 times higher than the overhead of a minimal object in Java.
I also looked at the "retained size" of var's which is a very good indicator of what binding currently costs. See also my other blog about "retained size".

I don't doubt that there are footprint improvements possible, and actually I posted this blog because I thought some data would be helpful.

Regards,
Markus

Unknown said...

I just filed a bug

Hire Java Programmers India said...

It is really great info to be checking the memory usage of the phone. I want to become a good android developer in the future. I have a good knowledge object of the JavaFX.