Java writeObject与writeUTF

Java writeObject与writeUTF,java,stream,Java,Stream,什么更快? out.writeObject(someString)或out.writeUTF(someString)不知道 把这两个都计时,它会以比我们更快的速度告诉你 for(int i=0; i<100000; i++) { out.writeObject(someString); } for(int i=0; i<100000; i++) { out.writeUTF(someString); } for(int i=0;i我假设结果可能取决于someStr

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

不知道

把这两个都计时,它会以比我们更快的速度告诉你

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

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

for(int i=0;i我假设结果可能取决于
someString
的内容。我想到,当使用更高的unicode点时,
writeUTF
性能会发生变化,因此输出是多字节的,这不是一个不合理的结果


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

我编写了一个测试用例,writeObject更快。一个可能的原因是“请注意,将字符串作为基本数据或对象写入流中有很大区别。writeObject写入的字符串实例最初作为字符串写入流中。Future writeObject()调用将字符串的引用写入流中。”请参阅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();

    }
}
100000次writeObject:464运行
100000次写入共享:5082
100000次写操作F:7541
导入java.io.*;
公共课写作
{
私有静态int运行=100000;
私有静态int STR_乘数=100;
publicstaticvoidmain(字符串[]a)抛出Throwable
{
StringBuilder=新的StringBuilder(26*STR_乘数);
对于(int i=0;i
我想让人们从这个问题中学到两件事:Java序列化是缓慢的——与之共存。微基准比失败更糟糕

微基准点往往具有误导性。作为一种通用习惯用法,有一些事情值得做(例如,在C中将strlen从循环中提升出来)。优化者有打破微基准的习惯。在实际负载下使用你的应用程序并对其进行分析。如果某段代码导致你的程序速度减慢,不要费心对其进行优化。微基准不会帮助你找到这些位置

writeObject和writeUTF的作用不同。writeObject指示要写入的对象类型。另外,如果自上次重置后已写入同一对象(字符串),writeObject只写回引用。writeUnshared更接近writeUTF

因此,如果您继续写入完全相同的长字符串,writeObject应该会赢,因为它只需要写回引用。减少序列化大小可能会减少文件/网络带宽或内存,这可能会导致更显著的性能改进。对于短字符串,只需写出数据就会更快。writeUnshared should提供几乎可写的性能,但保持通用性


请注意,在所有情况下,数据都是以UTF-8而不是UTF-16的形式写入的。如果希望使用UTF-16
String,则可以使用toCharArray
或类似的格式。

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

您应该知道writeUTF只能处理长度<65535的字符串…

当然您可以通过分析自己解决这个问题。值得一提的是:
writeUTF
不处理
null
。这有点令人惊讶,因为writeObject在内部检查对象是否为字符串,然后调用writeUTF。@andrewFinnell,是的,我确认了结果,但我不确定为什么。你是对的,没有UTF-16和UTF-8的区别(writeString调用writeUTF,它被修改为UTF-8)。它可能最终成为一个测试工件。我特别不确定writeUnshared在做更多事情和写重复副本时为什么会更快。这难道不是一个不做微基准测试的好例子吗?@nilskp,它显然又快又脏,可能有缺陷。但你的评论没有帮助,因为它没有解释你在做哪一部分nk会影响结果。@MatthewFlaschen,你是对的,这里有一个开始:然后切换循环的顺序,并惊讶于这告诉你的是多么少。