After looking at the (patched, above) code to VelocityCharStream.java, I'm not sure where all the memory savings is coming from.
I'm guessing that the patched version just includes a trip through the StringImagePool to 'canonicalize' the strings. The only overhead that is being saved is the overhead of additional String objects (keep reading).
The bulk of a String object is usually its character array representing the contents of the String. Since Strings are immutable, the Java folks figured they'd use that to their advantage and share character arrays between String objects created from each other. That means that if you start out with a big String and create lots of little substrings from that first once, you get lots of objects, but only a single copy of the actual content (one big char array and lots of indexes into it).
Has anyone actually observed any significant memory savings from this?
I seem to recall that the minimum byte overhead for any object is about 8 bytes (that includes the superclass pointer, etc.). The String class contains 3 4-byte ints and a reference to the char array (# of bytes depend on the architecture, VM, etc.). Assuming a vanilla 32-bit VM with no tricks, we're talking about adding 16 bytes to the existing 8 byte overhead for a grant total of 24 bytes per String object (remember, the character array should be shared).
Perhaps there are so many of these little objects lying around that simply removing all the extra copies of "else" really helps.
Are there other places where tons of memory gets used? The memory map I see attached to this bug suggests that the Template objects are responsible for a lot of memory. I imagine that an AST is built from the original text of the template. Do we continue to keep the text of the template in memory after parsing? It seems to me that the template texts themselves could add up if they're being kept around in memory.
Anyone care to comment?