Performance Day One

Performance is often underrated in the early and middle stages of development. When the product is almost finished, components have been integrated and working together in a complex solution. Then any performance issues become more visible. 

Performance can be addressed at the architecture, design, or code level. In this blog, we focus on the code level where small changes can be done with a small cost but significant gain.

Comparison of strings

Comparing strings is widely used. In the following part, we evaluate different approaches to string comparison. We chose the most popular core Java 11 implementations and the widely used Apache StringUtils library.

The following was done:

  • Compared two 12-character long strings with a different last character,
  • Used System.nanoTime() to measure the time.
Time:[picos]Time:[ms]Time:[ms]Time:[ms]
LabelEquals1 time5 million times10 million times20 million times
E1a.equals(b)0.3861.9293.7297.71
E2a.compareTo(b)0.4261.9373.78.519
E3Objects.equals(a, b)0.4091.8673.9158.176
E3StringUtils.equals(a, b)1.1905.91211.47223.801
 EqualsIgnoreCase 
IG1a.equalsIgnoreCase(b)18.75193.19191.512375.027
IG2a.compareToIgnoreCase(b)==011.53757.488108.275230.744
IG3StringUtils.equalsIgnoreCase(a,b)16.788103.436197.758335.761
IG4StringUtils.compare(a, b) == 07.15336.58580.412143.052

The results shows we avoid comparing strings using ignore case when possible and use simple equals instead. However, there is a clear winner when needing ignore case: StringUtils.compare(a, b) == 0 is much faster than anything else. If we can’t use this Apache library, stick to the Java a.compareToIgnoreCase(b) == 0.

String concatenation

String concatenation can be done in multiple ways, and we will present the impact of chosen approaches on performance.

The following was done:

  • Concatenate two 12-character long strings,
  • Used System.nanoTime() to measure the time,
  • A new builder was created for each append.
Time:[ms]Time:[ms]Time:[ms]
Compare method1 million times5 million times10 million times
concat51.30779.989131.339
builder12.16441.17881.699
+24.18546.7378.876
format260.557777.7331522

Using String.format is expensive, so we should use it with caution; a simple add or string builder might be better. However, String.format doesn’t just concatenate, it does much more and is easier to read and maintain; so it might be the right choice. You have to decide.

Conclusion

This article covered two common usages around strings, and as we saw, simple changes can make a big difference. Performance isn’t the only consideration, it is essential to consider other factors like maintainability. 

Sometimes, slightly less performant methods with higher readability are a better choice. 

Other times, the worst performant method may be the best choice. For example, String.format might be easier to read and maintain, and provide additional functionality, making the worst performing choice the right one.

Dariusz Czajkiewicz
Senior SDET


Watch or read our other posts at Kimputing Blogs. You’ll find everything from Automated testing to CenterTest, Guidewire knowledge to general interest. We’re trying to help share our knowledge from decades of experience.

Similar Posts