Win a copy of Think Java: How to Think Like a Computer Scientist this week in the Java in General forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Avoiding memory allocation?

 
Dan Bizman
Ranch Hand
Posts: 387
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've read in a number of places the recommendation that you should avoid memory allocation (in Java) wherever possible. How is this done? I thought Java was a memory-managed language where you didn't have control over that. Are there ways to avoid memory allocation? What are they? Are they worth it?
 
Peter Chase
Ranch Hand
Posts: 1970
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Most places that recommend avoiding allocation are very old and/or just plain wrong. Modern JVMs are very fast at allocation and deallocation. They have special generational garbage-collectors to help with this.

However, Java objects are always initialised after allocation. Even if there is no programmer-generated code to assign initial values, the JVM is required to assign agreed values to fields etc. Therefore, initialisation of objects with a lot of fields could take significant time. Arrays are also always initialised, so very large arrays can take a lot of time to initialise.

Some objects lend themselves to re-use. If this is the case, then by all means re-use objects and save on allocation/initialisation/deallocation costs. But do not compromise the understandability of your code to enable re-use.

In my code, I do occasionally do things explicitly to enable re-use. But this is only done when profiling has shown these to be benficial. In particular, I have a "recycler" for big byte arrays, because I use a lot of big byte arrays and initialising lots of new ones was getting expensive.
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24211
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Don't avoid allocation; avoid excessive and unnecessary allocation.

The classic example is something like this:



Each time through the loop, this allocates several StringBuffer objects, which each contain an array, and several Strings, which each contain an array -- something like 80,000 objects altogether. That's a lot of work for the JVM, especially since code that does the same thing while allocating only four objects (one StringBuffer, one String, and their member arrays) is no more complex:



(If you don't believe me about buffer.append(i) not allocating any objects, go look at the source code -- it's very highly optimized.)
 
Dan Bizman
Ranch Hand
Posts: 387
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Ernest Friedman-Hill:
Don't avoid allocation; avoid excessive and unnecessary allocation.

The classic example is something like this:



Each time through the loop, this allocates several StringBuffer objects, which each contain an array, and several Strings, which each contain an array -- something like 80,000 objects altogether. That's a lot of work for the JVM, especially since code that does the same thing while allocating only four objects (one StringBuffer, one String, and their member arrays) is no more complex:



(If you don't believe me about buffer.append(i) not allocating any objects, go look at the source code -- it's very highly optimized.)


Thanks for the reply.

The only examples I've seen are of String usage. Are there others to be mindful of?

I do try to reuse objects where possible, and if I can null out the references when they're no longer needed. But I'm guessing that's a small to zero gain.
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24211
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The fact that Strings are a handy example for this kind of discussion have led some people to believe that Strings are evil. That's not true at all; it's just that an example like this is easy for people to understand and this kind of thing comes up so often in real code. I think the crucial reason for this is that the allocation is hidden -- you don't call "new", so you don't think about it. Neither the right way nor the wrong way involves calling "new".

A similar kind of thing that does involve calling new would be accumulating primitives in an array. Let's say you're writing a class like ArrayList which holds an int[] internally. There's an add() method which adds an item to the array.

There are two ways to write a class like this: a wrong way which allocates lots of unnecessary objects, and a right way which doesn't. The wrong way is to have the array always be the exact right size. Whenever add() is called, you create an array one element longer, copy the old data, insert the new int, discard the old array. Every add() causes an allocation and data copy. When the array gets big, this can get expensive! I've seen lots of newbie code like this.

The other strategy is to keep a separate count of the valid elements in the array, and let the array be bigger-than-needed most of the time. Then you only have to allocate-and-copy occasionally, at the expense of a little wasted space. It's generally a good trade!
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Dan Bizman:
I do try to reuse objects where possible


Be aware that very short lived objects are actually better for the GC than objects with a medium live time. So, if you reuse objects blindly, you could in fact make things worse.


null out the references when they're no longer needed


You know that you don't need to do that when the reference gets out of scope anyway?

But I'm guessing that's a small to zero gain.


Yes, if at all. It really only makes sense in *very* specific cases. Typically it will do more harm than good, if "only" by making the code more complex than necessary.
 
Ken Blair
Ranch Hand
Posts: 1078
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Ilja Preuss:
You know that you don't need to do that when the reference gets out of scope anyway?


Which is why you should be mindful of exposing references and variables in general to excessive scope.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, it's one reason, not the only one.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic