Fastest way to release memory of stringbuilder

Viewed 3566

What is the fastest way to release memory of stringbuilder .

 StringBUilder sb = new StringBuilder();
 sb.apppend(maximum value possible);

Below are the code snippets which i tried to release memory as fast as possible and make the object eligible for garbage collection

Option 1:

sb = null;

As per my understanding all the data in the stringbuilder will be deleted and object will be eligible for garbage collection as soon as it is kicked in, but the memory of the text which is occupied by stringbuilder will be released. Also will the string value in it also be deleted from heap or will be stored in string pool ?

Option 2:

 sb.setLength(0);

This will reset the lenght of string builder but it will not be garbage collected

Option 3:

 sb.delete(0,sb.length());

This will reset the string builder by deleting all the data in it but it will not be garbage collected

Option 4:

 sb.delete(0,sb.length());
 sb = null;

This will reset the string builder and also make it eligible for garbage collection?!

5 Answers

If you really want the memory to be released as fast as possible, then GC options are where you need to look, not code.

A detailed analysis of GC options for this purpose is beyond what can sensibly fit here - but specifically, the new Shenandoah GC can be tuned to be much more aggressive at releasing memory than G1 or concurrent mark/sweep, so this is probably what you'd want to use. You can specify this with -XX:+UseShenandoahGC. (It's OpenJDK specific and experimental at this point, but if you want the behaviour you're after, it's the one to go for.)

For fast release times, you would want to use a small value for ShenandoahUncommitDelay and ShenandoahGuaranteedGCInterval. Smaller values here (broadly speaking) will run the GC more often and more aggressively, therefore using more CPU cycles - but it will have the effect that you're after, that memory will be released incredibly quickly in comparison to previous GC incarnations.

If you just want to make sure that the memory is released so it's eligible for garbage collection quickly, then you just need to make sure all references to that StringBuilder are set to null at the soonest opportunity. Even in this case though, I'd encourage you to profile and check if you need to do this explicitly - in many cases now, the JVM is smart enough to mark objects as eligible for GC even if they're technically still in scope (so long as it can see they're no longer referenced for the remainder of that scope.)

Simple: go with

sb = null;

and forget about the rest.

Why? As soon as the GC can decide that an object is eligible for garbage collection, it also knows that all the things referenced from that object are eligible. And given the fact that you have no control about the GC kicking in and cleaning up objects and releasing memory, the above assignment is really good enough.

As it communicates your intent clearly, and then helps the GC to do its job. Actually well written code would probably not even need that statement.

Now, maybe that is actually not good enough. But then we would be talking about a real performance issue, in a very defined and narrow context. In that case, you don't rely on hearsay, you start measuring.

In other words: if you don't have a real performance issue that manifests in your setup, and that requires action, then you go with simple, clear code, avoiding all kinds of "source code level" optimisations. But if you have a real performance issue, than you treat that accordingly: by identifying the root cause, and probably by measuring how different options work out in reality.

Anything else smells of premature optimisation!

The only safe way to ensure that the StringBuilder is eligible for garbage collection is the same as all objects: kill all references to it. That means explicitly setting it to null or letting it drop out of scope.

Beyond that, you have no control over when the memory is released. The most you can do is request garbage collection, and that's rarely a good idea (not to mention you are just requesting, not ordering the JVM to garbage collect).

The other choices you proposed are not guaranteed to free up all of the memory unless you've done a deep dive into the code and are confident that you are fully flushing the object's state. That's why it's usually much better to just null the entire object reference and start over if you want to make sure everything is "clean."

Just let the StringBuilder object go out of scope (at the closing curly brace) and don't clutter your code with unnecessary statements in a vain attempt to make the garbage collector do its work more quickly. When the StringBuilder object goes out of scope, it will become eligible for garbage collection. Keep your source code clean.

A possible solution includes 3 steps:

  1. call sb.setLength(0). This will set the string builder internal length to 0 and is needed for step 2.
  2. call sb.trimToSize(). This will replace the value array with a new trimmed array, in our case a char[] of size 0
  3. sb = null will remove your reference to the StringBuilder.

If the string builder is only used by you and is not passed anywhere else, this should make the previous value array and the string builder eglibe for garbage collection.

Though when that actually happens depends still on the JVM and so the "fastest way" is probably not possible as it is in fact quite random.

Related