When I refactored FlexibleStringExpander.java a while ago (rev 687442), there were things I wanted to improve but couldn't - because I wanted to maintain backward-compatibility.

Adam's recent memory-saving efforts reminded me of one of the things I wanted to change in FlexibleStringExpander.java - I wanted to make the object more lightweight.

OFBiz can hold anywhere from tens of thousands to hundreds of thousands of these objects in memory, so an object size reduction could be beneficial.

With that under consideration, I would like to do a little more work on the class. What I have in mind is to keep the existing API the same - to preserve backward compatibility - but add an interface so that we can make gradual changes to framework code that will improve memory use.

Here are the changes I have in mind:

1. Extract an interface from FlexibleStringExpander, call it something like StringExpression. 2. Convert FlexibleStringExpander to an abstract class that implements StringExpression. 3. Have FlexibleStringExpander's nested classes extend FlexibleStringExpander. 4. Reduce object size by having each FlexibleStringExpander subclass contain only the objects it needs.

This is an initial step - nothing changes from the API point of view. No changes would need to be made to framework code.

As time and resources permit, we can gradually change lines like:

FlexibleStringExpander fse = FlexibleStringExpander.getInstance(expression);

to:

StringExpression se = FlexibleStringExpander.getInstance(expression);

and both versions will work the same.

After all FlexibleStringExpander instances have been replaced with StringExpression instances, we can extract the FlexibleStringExpander nested classes into individual files, have them implement StringExpression, and remove the class extension. FlexibleStringExpander then becomes nothing more than a factory and some static convenience methods.

That's it. If you want to know how this will benefit memory use, read on...

Consider this mini-language statement:

<set field="isTrue" value="Y"/>

The value attribute is kept in memory as a FlexibleStringExpander instance. That instance will contain one instance of ConstElem that contains the String "Y". So, let's tally up the memory used for this single character:

FlexibleStringExpander fields:

  String orig = "Y"
  List strElems = a List with one ConstElem element
  int hint = 20 (used as a StringBuilder initial size)

ConstElem fields:

  String str = "Y"

That's a lot of overhead to store a single character. After the proposed refactor, the value attribute will be kept in memory as a ConstElem instance - which will contain nothing more than the String "Y".

The ConstElem class really doesn't need the String class methods, so we can eliminate the String instance too - by storing it as a character array. Now the "Y" StringExpression instance takes up the same space as a String object.

What do you think?

-Adrian

Reply via email to