Java writeObject Vs. writeUTF

时间:2009-06-08 12:04:48

标签: java stream

什么更快?
out.writeObject(someString)或out.writeUTF(someString)

6 个答案:

答案 0 :(得分:8)

我希望人们从这个问题中学到两件事:Java序列化很慢 - 与它一起生活。微观标记比失败更糟糕。

微型商标往往会产生误导。有一些东西值得做一般的习惯用法(例如,在C中将strlen从循环中提升)。优化者习惯于打破微基准。获取您的应用程序并在实际负载下进行分析。如果一段代码导致程序变慢,请不要费心去优化它。 Microbenchmarks不会帮助您找到这些地方。

writeObject和writeUTF不会做同样的事情。 writeObject指示它要写入的对象类型。如果自上次重置以来已写入相同的对象(字符串),writeObject也会写入后引用。 writeUnshared更接近writeUTF。

因此,如果你继续写完全相同的长字符串writeObject应该赢,因为它只需要写一个后引用。减少序列化大小可能会降低文件/网络带宽或内存,这可能会带来更显着的性能提升。对于短字符串,只需写出数据就会更快。 writeUnshared应该提供几乎writeUTF性能,但保持通用性。

注意,在所有情况下,数据都写为UTF-8而不是UTF-16。如果你想要UTF-16 String.toCharArray或类似的话。

答案 1 :(得分:4)

我写了一个测试用例,而writeObject更快。一个可能的原因是因为“请注意,将String作为基本数据或作为Object写入流中之间存在显着差异。将writeObject写入的String实例最初作为String写入流中。将来的writeObject()调用write将字符串引用到流中。“请参阅writeObject文档。

编辑:但是,writeUnshared仍然比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();

    }
}

答案 2 :(得分:1)

我认为结果可能取决于someString的内容。在我看来,发现writeUTF性能发生变化并不是一个不合理的结果,因为使用了更高的unicode点,因此输出是多字节的。

请注意这是未经证实的,只是一个空想。

答案 3 :(得分:1)

你应该知道writeUTF只能处理长度为&lt;的字符串。 65535 ...

答案 4 :(得分:0)

不知道。

时间都是这些,它会比我们更快地告诉你。

for(int i=0; i<100000; i++) {
    out.writeObject(someString);
}

for(int i=0; i<100000; i++) {
    out.writeUTF(someString);
}

答案 5 :(得分:0)

使用DataOutputStrema.writeUTF()可以获得比ObjectOutputStream.writeUTF()更好的性能。