Error message

  • Notice: Trying to get property of non-object in filter_default_format() (line 532 of /home/ntroutman/webapps/nt_drupal/modules/filter/filter.module).
  • Notice: Undefined variable: options in filter_process_format() (line 911 of /home/ntroutman/webapps/nt_drupal/modules/filter/filter.module).

Performance of Clearing a StringBuilder

The other day at work I was working on a project where I would be creating lots of small strings. And by a lot, I mean a lot, on the order of 100s of millions. So, I was wondering what is the most efficient way to deal with using StringBuilder. Building the strings would require dumping the contents of the builders. There are three methods, reallocating a new string builder each time, using sb.setLength(0), or sb.delete(0, sb.length()). Being the empirical scientist that I am, I figured the only way to determine which is the fastest is to profile it.

So I set some experiments. The idea is to time appending a bunch of strings to a string builder, clearing it, then doing it all over again. The code looks something like this for the reallocation technique:

long start = System.nanoTime();
for ( int i = 0; i < 100000; i++ ) {
    StringBuilder sb = new StringBuilder();
    int numAppends = getNumAppends();
    for ( int i = 0; i < numAppends; i++ ) {
        sb.append(theString);
    }
}
long end = System.nanoTime();

getNumAppends() picks a random number of times to append the string so that we get some variation, it varies between n/2 and n, with n being 10 or 50. However, I seed the random number generator with the same seed before testing each technique to ensure the same sequence of numAppends happens. I also vary the length of the string being appened, doing 8, 32, and 1024 bytes. Here are the results.

 

String Length: 8, AppendsRange: 10
Time(cls= Reallocate:appends=  700017) :     121,888,000
Time(cls=  SetLength:appends=  700017) :      53,434,000
Time(cls=     Delete:appends=  700017) :      57,679,000

String Length: 8, AppendsRange: 50
Time(cls= Reallocate:appends= 3699937) :     395,175,000
Time(cls=  SetLength:appends= 3699937) :     235,365,000
Time(cls=     Delete:appends= 3699937) :     234,827,000

String Length: 32, AppendsRange: 10
Time(cls= Reallocate:appends=  700017) :     182,203,000
Time(cls=  SetLength:appends=  700017) :      62,461,000
Time(cls=     Delete:appends=  700017) :      63,457,000

String Length: 32, AppendsRange: 50
Time(cls= Reallocate:appends= 3699937) :     796,013,000
Time(cls=  SetLength:appends= 3699937) :     302,334,000
Time(cls=     Delete:appends= 3699937) :     299,673,000

String Length: 1024, AppendsRange: 10
Time(cls= Reallocate:appends=  700017) :   2,250,015,000
Time(cls=  SetLength:appends=  700017) :     183,259,000
Time(cls=     Delete:appends=  700017) :     236,697,000

String Length: 1024, AppendsRange: 50
Time(cls= Reallocate:appends= 3699937) :  25,990,128,000
Time(cls=  SetLength:appends= 3699937) :   1,054,074,000
Time(cls=     Delete:appends= 3699937) :   1,068,460,000

From this it looks like setLength() is generally the fastest.

While looking around I found mention of one of the key factors for speed is to initialize the capacity of the string builder to something close to the needed size to avoid having to allocate additional memory. So, I reran the tests this time initializing the builder's capacity to ensure it had enough room for the eventual size of the string.

String Length: 8, AppendsRange: 10
Time(cls= Reallocate:appends=  700017) :      63,626,000
Time(cls=  SetLength:appends=  700017) :      56,697,000
Time(cls=     Delete:appends=  700017) :      54,320,000

String Length: 8, AppendsRange: 50
Time(cls= Reallocate:appends= 3699937) :     267,833,000
Time(cls=  SetLength:appends= 3699937) :     229,641,000
Time(cls=     Delete:appends= 3699937) :     227,320,000

String Length: 32, AppendsRange: 10
Time(cls= Reallocate:appends=  700017) :      85,281,000
Time(cls=  SetLength:appends=  700017) :      65,403,000
Time(cls=     Delete:appends=  700017) :      65,799,000

String Length: 32, AppendsRange: 50
Time(cls= Reallocate:appends= 3699937) :     412,411,000
Time(cls=  SetLength:appends= 3699937) :     275,545,000
Time(cls=     Delete:appends= 3699937) :     278,557,000

String Length: 1024, AppendsRange: 10
Time(cls= Reallocate:appends=  700017) :     832,667,000
Time(cls=  SetLength:appends=  700017) :     198,386,000
Time(cls=     Delete:appends=  700017) :     202,099,000

String Length: 1024, AppendsRange: 50
Time(cls= Reallocate:appends= 3699937) :   4,654,792,000
Time(cls=  SetLength:appends= 3699937) :   1,052,807,000
Time(cls=     Delete:appends= 3699937) :   1,066,031,000

Again, setLength() is the winner. But the difference in speed between pre-initializing the capacity and not seems to be relatively small.

Add new comment