Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

I've been writing some code recently that manipulates lots of strings, specifically it does appends on them via a Writer. In Java there are two choices when it comes to a Writer that's oriented around Strings - CharArrayWriter and StringWriter. I got curious about which one would be best in terms of performance, these are my findings.

I think the graph below more or less tells the story.
StringVsCharArrayWriter.png


There is absolutely no performance difference regarding which Writer you choose. That's the short story anyway.

The longer story goes something like this...

According to the JDK 7 documentation for StringWriter, it is backed by a StringBuffer, which is thread-safe. However the CharArrayWriter documentation says it is backed by a simple char array. This may lead one to think that CharArrayWriter is not thread safe. That's what I thought as there is no mention of it otherwise.

You'd be wrong if you thought that CharArrayWriter is not thread safe. Examining the code reveals that all the critical parts of the code are wrapped with a synchronized block. This makes it equivalent to StringWriter's thread-safe StringBuffer. CharArrayWriter is thread safe.



I did investigate a little bit more and even wrote some code that used a single CharArrayWriter between multiple threads to see if I could produce inconsistent appends, this didn't not happen in any of my tests. I used a regex pattern to test my generated string after every test.

This is the code I used to test. Swap the StringWriter/CharArrayWriter as needed.
 WriterTest.java
import java.io.CharArrayWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WriterTest {
private static Pattern matchPattern = Pattern.compile("(Test)+");
public static final void main(String[] args)
throws InterruptedException
{
int runs = 1000000;
int tests = 100;
int threads = 10;
multiThreadTest(tests, runs, threads);
}
private static void multiThreadTest(int tests, int runs, int threadsCount)
throws InterruptedException
{
Thread[] threads = new Thread[threadsCount];
for (int j = 0; j < tests; j++) {
CharArrayWriter writer = new CharArrayWriter();
for (int i = 0; i < threadsCount; i++) {
threads[i] = new WriterThread(writer, runs);
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < threadsCount; i++) {
threads[i].start();
}
for (int i = 0; i < threadsCount; i++) {
threads[i].join();
}
String str = writer.toString();
long endTime = System.currentTimeMillis();
Matcher m = matchPattern.matcher(str);
System.out.println(endTime-startTime + "\t" + m.matches());
}
}
static class WriterThread extends Thread {
CharArrayWriter writer;
int runs;
public WriterThread(CharArrayWriter writer, int runs) {
this.writer = writer;
this.runs = runs;
}
@Override
public void run() {
for (int i = 0; i < runs; i++) {
writer.append("Test");
}
}
}
}


The only discernible difference I could see is with CharArrayWriter you can get access to the backing char array (or copy of it at least) directly whereas its a little bit more work to get the char array when using StringWriter.

I was a little surprised that CharArrayWriter is thread safe and would like to see an unsynchronized implementation of a string based writer in the JDK in the future.

-i

A quick disclaimer...

Although I put in a great effort into researching all the topics I cover, mistakes can happen. Use of any information from my blog posts should be at own risk and I do not hold any liability towards any information misuse or damages caused by following any of my posts.

All content and opinions expressed on this Blog are my own and do not represent the opinions of my employer (Oracle). Use of any information contained in this blog post/article is subject to this disclaimer.
Hi! You can search my blog here ⤵
NOTE: (2022) This Blog is no longer maintained and I will not be answering any emails or comments.

I am now focusing on Atari Gamer.