What is faster?
out.writeObject(someString) or out.writeUTF(someString)
6 Answers
There are two things I want people to learn from this quesiton: Java Serialisation is slow - live with it. Microbenchmarks are worse than failure.
Microbenchmarks tend to be misleading. There are some things that are worth doing as a general idiom (for instance, hoisting strlen out of loop in C). Optimisers have a habit of breaking microbenchmarks. Take your application and profile it under real load. If a piece of code is causing your program to slow down, don't bother to optimise it. Microbenchmarks will not help you find these places.
writeObject and writeUTF don't do the same thing. writeObject indicates what type of object it is going to write. Also writeObject just writes a back reference if the same object (string) has been written since the last reset. writeUnshared is closer to writeUTF.
So if you continue to write exactly the same long String writeObject should win because it just needs to write a back reference. Reducing serialised size may reduce file/network bandwidth or just memory, which may result in more significant performance improvements. For short strings, just writing out the data will be faster. writeUnshared should give almost writeUTF performance, but maintaining generality.
Note, in all cases that data is written as UTF-8 not UTF-16. If you want UTF-16 String.toCharArray
or similar will do.

- 145,806
- 30
- 211
- 305
I wrote a test case, and writeObject is faster. One possible reason is because "Note that there is a significant difference between writing a String into the stream as primitive data or as an Object. A String instance written by writeObject is written into the stream as a String initially. Future writeObject() calls write references to the string into the stream." See the writeObject documentation.
EDIT: However, writeUnshared is still faster than writeUTF,
100000 runs of writeObject: 464
100000 runs of writeUnshared: 5082
100000 runs of writeUTF: 7541
import java.io.*;
public class WriteString
{
private static int RUNS = 100000;
private static int STR_MULTIPLIER = 100;
public static void main(String[] a) throws Throwable
{
StringBuilder builder = new StringBuilder(26 * STR_MULTIPLIER);
for(int i = 0; i < STR_MULTIPLIER; i++)
{
builder.append("abcdefghijklmnopqrstuvwxyz");
}
String str = builder.toString();
File f = new File("oos");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
long startObject = System.currentTimeMillis();
for(int i = 0; i < RUNS; i++)
{
oos.writeObject(str);
oos.flush();
}
long endObject = System.currentTimeMillis();
System.out.println(RUNS + " runs of writeObject: " + (endObject - startObject));
long startUnshared = System.currentTimeMillis();
for(int i = 0; i < RUNS; i++)
{
oos.writeUnshared(str);
oos.flush();
}
long endUnshared = System.currentTimeMillis();
System.out.println(RUNS + " runs of writeUnshared: " + (endUnshared - startUnshared));
long startUTF = System.currentTimeMillis();
for(int i = 0; i < RUNS; i++)
{
oos.writeUTF(str);
oos.flush();
}
long endUTF = System.currentTimeMillis();
System.out.println(RUNS + " runs of writeUTF: " + (endUTF - startUTF));
oos.close();
f.delete();
}
}

- 278,309
- 50
- 514
- 539
-
This is kind of surprising seeing as writeObject internally checks for the object being a String, then calls writeUTF. – Andrew T Finnell Oct 24 '12 at 19:38
-
@AndrewFinnell, yes, I confirmed the results, but I'm not sure why. You're right that there are is no UTF-16 v. UTF-8 distinction (writeString calls writeUTF, which is modified UTF-8). It could end up being a testing artifact. I'm particularly not sure why writeUnshared is faster when it does more and writes duplicate copies. – Matthew Flaschen Oct 25 '12 at 04:03
-
1
-
1@nilskp, it's obviously quick and dirty, and there may be flaws. But your comment is not helpful, since it doesn't explain which part you think compromises the results. – Matthew Flaschen Jul 18 '13 at 19:46
-
1@MatthewFlaschen, you're right, so here's a starter: http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – nilskp Jul 19 '13 at 18:59
You should be aware that writeUTF can only handle Strings with a length < 65535...

- 4,242
- 3
- 33
- 31
I would assume that the result may depend on the contents of someString
. It occurs to me that it wouldn't an unreasonable result to find that writeUTF
performance changes as the higher unicode points are used such that the output is multi byte.
Please note this is unproven and is just an idle thought.

- 27,701
- 12
- 73
- 106
No idea.
Time both of these and it'll tell you faster than we can.
for(int i=0; i<100000; i++) {
out.writeObject(someString);
}
for(int i=0; i<100000; i++) {
out.writeUTF(someString);
}

- 21,816
- 3
- 61
- 76
-
Then switch the order of the loops and be amazed at how little this tells you. – nilskp Jul 18 '13 at 15:37
You will get better performance with DataOutputStrema.writeUTF() than ObjectOutputStream.writeUTF().

- 525,659
- 79
- 751
- 1,130