I'm a c++ developer by trade, but I've been doing a bit Java lately. This project I'm working in was done by a developer long since gone and I keep finding things where he is working around the Garbage collection by doing weird things.
Case and point he implemented his own string class to avoid slow down by GC
This section of the app takes a large binary file format and exports it to csv. This means building up a string for each line in the file (millions). In order to avoid those temporary string objects he made a string class that just has a large array of bytes he reuses.
/**
HACK
A Quick and Dirty string builder implementation optimized for GC.
Using String.format causes the application grind to a halt when
more than a couple of string operations are performed due to the number of
temporary objects allocated while formatting strings for drawing or logging.
*/
Does this actually help? is this really needed? Is this better than just declaring a String object outside the loop and setting it inside the loop?
The app also has a hash map containing doubles for the values. The keys in the map are fairly static but the values change often. Afraid of GC on doubles he made a myDouble class to use as the value for the hashmap
/**
* This is a Mutable Double Wrapper class created to avoid GC issues
*
*/
public class MyDouble implements Serializable {
/**
*
*/
private static final long serialVersionUID = C.SERIAL_VERSION_UID;
public double d;
public MyDouble(double d) {
this.d = d;
}
}
This is crazy and completely unnecessary... right?
An object is eligible to be garbage collected if its reference variable is lost from the program during execution. Sometimes they are also called unreachable objects.
What is Java Garbage Collection? Java applications obtain objects in memory as needed. It is the task of garbage collection (GC) in the Java virtual machine (JVM) to automatically determine what memory is no longer being used by a Java application and to recycle this memory for other uses.
By Increasing Heap Memory This approach leads to the garbage collector running infrequently, however when it runs, will take longer than before to complete the garbage collection task.
We have three ways to achieve same - 1) Increasing the Heap -Eden space size . 2) Create Singleton class with Static reference . 3) Override finalize() method and never let that object dereference.
It's true that string concatenation can be a bottleneck in Java because String
s are immutable. This means each concatenation creates a new String
, unless a matching String
was previously created and is therefore in the string-pool (see string interning). Either way, it can certainly lead to problems.
However your predecessor is not the first person to have encountered this and the standard way to deal with the need to concatenate many String
s in Java is to use a StringBuilder.
When a double
(or any primative for that matter) is used as a local variable, it's kept on the stack and the memory it occupies released along with the stack frame (non sure if they're subject to GC or taken care of by the JVM as it runs). If however the double
is the field on an object, it's stored on the heap and will be collected when the object containing it is collected.
Without seeing how the double
values are being used, it hard to say for sure, but it's more than likely the use of the Map
has increased the GC load.
In summary, yes, imho this is certainly, as you say 'crazy and completely unnecessary'. These sorts of premature optimizations only serve to complicate the code base making it more prone to bugs and making future maintenance more difficult. The golden rule should practically always be, build the simplest thing that works, profile it and then optimize.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With