Use of default constructors for StringBuffer and StringBuilder throughout the code generates lots of memory churn

Description

The 5.16.3 code base has hundreds of instances of "new StringBuffer()" and "new StringBuilder()", using the default constructor rather than passing an initial buffer size. Both of this objects, by default, allocate a buffer of only 16 characters. Once that is filled up, the buffer is increased by:

a) guessing at new size. I think these days it triples the existing size and adds 2.
b) allocating a new internal buffer of that size.
c) copying the existing buffer into the new one.

Since allocating and copying memory are fairly expensive, avoiding this is better, if possible. And it usually is with string buffers, because you can guess at how big the final string will be.

An example from the code, picked at random:

pcgen.core.Description.getDescription.

Let's say that the end result of this method returns a string that is 200 characters long. Process would:

a) buf allocated with a capacity of 16 characters.
b) When 17th character is added, capacity increases to (probably) 50. New buffer allocated, contents of old one copied in.
c) When 51st character is added, capacity increases to (probably) 152. New buffer allocated, contents of old one copied in.
d) When 153rd character is added, capacity increases to (probably) 457. New buffer allocated, contents of old one copied in.

The end result of this is two more memory allocations than needed and the expensive copy operations.

In this particular case, something like buf = new StringBuffer(128) or new StringBuffer(256) is a better idea.

In a sample of some of the others, it looks like you could probably do a quick find/replace on StringBuffer() to StringBuffer(64) and get most of the way there. Better to look at each one individually, of course, but more time consuming.

Also, StringBuilder is faster, so many of the StringBuffer calls should probably use StringBuilder instead. The only reason to used StringBuilder is if you will have multiple threads appending to the same buffer, which almost never happens. (Chances are these are all legacy calls from a time when StringBuilder didn't exist.)

Environment

Source code

Activity

Show:
James Dempsey
October 3, 2010, 6:59 AM

No point looking at this type of issue in the prod branch. Moving report to be against the trunk.

Tom Parker
June 30, 2014, 11:27 AM

I have covered those encountered during LST load or runtime.

I have not bothered with those for error reporting, LST export, or file conversion, as those are either extremely rare or involve writing to disk which is exponentially slower than any small memory churn from no default size

Committed revision 24345.

Fixed

Assignee

Tom Parker

Reporter

Lester Ward

Labels

None

Theme

None

Epic/Theme

None

Pending User Input

None

Components

Fix versions

Affects versions

Priority

Minor
Configure