A per-document string pool is a feature of binary xml formats.<div><br></div><div>A potential problem with per-factory string pooling is the possibility of retaining large character arrays.  Android's String class description explains the problem:</div>
<div><br></div><blockquote class="gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span style="color:rgb(51,51,51);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">This class is implemented using a char[]. The length of the array may exceed the length of the string. For example, the string "Hello" may be backed by the array </span><code style="color:rgb(0,112,0);line-height:1em;font-size:13px;background-color:rgb(255,255,255)">['H', 'e', 'l', 'l', 'o', 'W'. 'o', 'r', 'l', 'd']</code><span style="color:rgb(51,51,51);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)"> with offset 0 and length 5.<br>
</span>Multiple strings can share the same char[] because strings are immutable. The <code style="color:rgb(0,112,0);line-height:1em"><a href="http://developer.android.com/reference/java/lang/String.html#substring(int)" style="color:rgb(0,102,153)">substring(int)</a></code> method <strong>always</strong> returns a string that shares the backing array of its source string. Generally this is an optimization: fewer character arrays need to be allocated, and less copying is necessary. But this can also lead to unwanted heap retention. Taking a short substring of long string means that the long shared char[] won't be garbage until both strings are garbage. This typically happens when parsing small substrings out of a large input. To avoid this where necessary, call <code style="color:rgb(0,112,0);line-height:1em">new String(longString.subString(...))</code>. The string copy constructor always ensures that the backing array is no larger than necessary.</blockquote>
<div><br></div><div>...from <a href="http://developer.android.com/reference/java/lang/String.html">http://developer.android.com/reference/java/lang/String.html</a></div><div><br></div><div>If xml parsers create new strings, is it to avoid retaining the entire source document?</div>
<div><br></div><div>I suggest choosing a name for the Slim factory that is more descriptive of what it does, as "slim" may depend on taste and application.<br><br>Joe<br><br><div class="gmail_quote">On Sat, Jan 28, 2012 at 8:38 AM, Rolf Lear wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi All ... An update...<br>
<br>
I have played with a number of options, and have not had significant success with any.<br>
<br>
Merging Content-list in to Element has a number of problems:<br>
1. Document and Element end up duplicating a lot of code<br>
2. It changes the API of Document and Element with it implementing List<Content><br>
<br>
Document and Element almost always contain content... it is seldom that you have empty Elements (there is normally some text at least). As a result, the savings of not having to have a content array are limited.<br>
<br>
There can be some saving in not having a separate object as the list, but it does not amount to much. Given the issues with the API this approach does not make sense.<br>
<br>
Michael Kay suggested keeping the ContentList independent of the Element, and creating an instance when it was referenced in getContent(). The problem with this is that the management of ConcurrentModification becomes very complicated, and, as far as I can tell, essentially impossible if there are multiple differet instances of the ContentList class for any particular Element. Given that almost all Element instances have content, it is not worth the effort to lose the ConcurrentModification control, and not actually save any memory in a typical use case.<br>

<br>
So, neither option for changing the ContentList system is very successful.<br>
<br>
On the other hand, it is relatively common to have no Attributes on an Element, and some careful changes to the Element class (adding a hasAttributes() method and making the AttributeList variable a 'lazy' initialised field) this means that in ideal cases we never need to actually create an AttributeList instance for the Element. This has a significant impact on the 'hamlet' test, where there are essentially no attributes. It has no 'negative' impact on memory in the worst case either, and it has positive (small but significant) impact on performance.<br>

<br>
So, the lazy initialization of AttributeList is a 'win'.<br>
<br>
Finally, I have in the past had some success with the concept of 'reusing' String values. XML Parsers (like SAX, etc.) typically create a new String instance for all the variables they pass. For example, the Element names, prefixes, etc. are all new instances of String. Thus, if you have hundreds of Elements called 'car' in your input XML, you will get hundreds of different String Element names with the value 'car'. I have built a class that does something similar to String.intern() in order to rationalize the hundreds of different-but-equals() values that are passed in by the parsers.<br>

<br>
I have incorporated this 'caching' class in to a new JDOMFactory called 'SlimJDOMFactory'. This factory 'normalizes' all String values to a single instance of each unique String value. This significantly reduces the amount of memory used in the JDOM tree especially if there are lots of: similarly named attributes, elements, white-space-padding in otherwise empty elements, or between elements. This process is significantly slower through...<br>

<br>
For example, with the 'hamlet' test case, the 'baseline' memory footprint for hamlet in JDOM is 2.27MB in 4.75ms.<br>
With the SlimJDOMFactory it is: 1.77MB in 8.5ms<br>
With Lazy AttributeList it is: 2.06MB in 4.55ms<br>
With the both it is 1.57MB in 8.3ms<br>
<br>
I am pushing both of these changes in to github. The AttributeList is an easy one to justify. It is fully compatible with prior code, it has positive memory and perfomance impacts.<br>
<br>
The SlimJDOMFactory is also justifiable when you consider:<br>
1. the user has to decide to use it specifically.<br>
2. The memory saving can be very significant.<br>
3. Even though the parse time is slower, the GC time savings can be significant if the document 'hangs around' for a long time - the quicker GC time can add up fast.<br>
4. When you have lots of code doing comparisons it is much faster to do equals() calls on Strings that are == as well. It saves a hashCode calculation as well as a string character scan to prove equals().<span class="HOEnZb"><font color="#888888"><br>

<br>
Rolf</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
On 02/01/2012 3:27 PM, Rolf wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi all.<br>
<br>
Memory optimization has never been a top priority for JDOM. At the same<br>
time, for what it does, JDOM is not a 'terrible' memory user. Still, I<br>
have done some analysis, and, I believe I can trim about a quarter to a<br>
half of 'JDOM Overhead' memory usage by making two 'simple' changes....<br>
<br>
The first is to merge the ContentList class in to the Element class (and<br>
also in to Document). This will reduce the number of Java objects by<br>
about half, and that will save about 32 bytes per Element at a minimum<br>
in a 64-bit JRE. Additionally, by lazy-initialization of the Content<br>
array, we can save memory on otherwise 'empty' Elements.<br>
<br>
This can be done by extending the Element (and perhaps Document) class<br>
to extend 'List'. It can all be done in a 'backward compatible' way, but<br>
also leads to some interesting possibilities, like:<br>
<br>
for (Content c : element) {<br>
... do something<br>
}<br>
<br>
(for backward compatibility, Element.getContent() will return 'this').<br>
<br>
<br>
The second change is to make the AttributeList instance in Element a<br>
lazy-initialization. This would save memory on all Elements that have no<br>
attributes, but would have an impact for people who sub-class the<br>
Element class and may expect the attributes field to be non-null.<br>
<br>
<br>
I am trying to get a feel for how important this sort of optimization<br>
may be. If there is interest then I will make some changes, and test the<br>
impact. I may make a separate branch in github to test it out....<br>
<br>
If the above changes are unrealistic then I don't think it makes sense<br>
to even try....<br>
<br>
Rolf<br></blockquote></div></div></blockquote></div></div>