I’ve now standardised my test cases to give a consistent test for each of the three options I’m playing with:
Beginning test cases... Testing name... append reader: StringBuilderAdapter took 11 millis. toString: StringBuilderAdapter took 2 millis. First run for StringBuilderAdapter took 13 millis. Second append: StringBuilderAdapter took 5 millis toString: StringBuilderAdapter took 9 millis. Second run for StringBuilderAdapter took 14 millis. Testing name... append reader: JumpRope took 6 millis. toString: JumpRope took 20 millis. First run for JumpRope took 26 millis. Second append: JumpRope took 0 millis toString: JumpRope took 7 millis. Second run for JumpRope took 7 millis. Testing name... append reader: TrefoilString took 11 millis. toString: TrefoilString took 18 millis. First run for TrefoilString took 29 millis. Second append: TrefoilString took 0 millis toString: TrefoilString took 8 millis. Second run for TrefoilString took 8 millis.
These numbers… are a little different than I’d previously believed. They shouldn’t be taken as definitive though – annoying things like “If I change the order of the tests around then the JIT optimises differently and the numbers change” and other random factors make them very variable.
Still, interesting points of note:
I’m a lot closer to StringBuilder level performance than I’d previously believed. The adapter slows it down a little, but these numbers were pretty close to what I’d been seeing with StringBuilder before – it’s the others that are much lower.
For lots of small appends, StringBuilder is about twice as fast as my implementations (the numbers are really really variable). For single large appends the situation is reversed.
There’s not a lot of performance difference between my dirty but supposed to be faster and my nice high level implementations. It turns out allocation is cheap after all.
Lessons to take out of this: I suck at performance testing and I need to set up some really extensive test suites if I want to get good performance numbers. Also, I should stick to a nice high level implementation and only worry about performance as a sanity check every now and then. Ho hum.