为什么ObjectOutputStream.writeObject在写入字节数组时比写入字节更快?

问题描述:

我做了一个小的基准测试,发现ObjectOutputStream.writeObject快于ObjectOutputStream.write(byte[] bytes),但我似乎无法找到一个可能的解释是引擎盖下,writeObject将调用ObjectOutputStream.write(byte[] bytes)间接为什么ObjectOutputStream.writeObject在写入字节数组时比写入字节更快?

测试代码

public static void main(String[] args) throws Exception { 
    byte[] bytes = new byte[10000]; 
    for (int i = 0; i < 10000; ++i) { 
     bytes[i] = (byte) (i % 256); 
    } 

    ByteArrayOutputStream out2 = new ByteArrayOutputStream(); 
    try(ObjectOutputStream ostream2 = new ObjectOutputStream(out2)) { 

     for (int i = 0; i < 10000; ++i) { 
      ostream2.writeInt(bytes.length); 
      ostream2.write(bytes, 0, bytes.length); 
     } 

     out2.reset(); 

     long start = System.nanoTime(); 
     for (int i = 0; i < 10000; ++i) { 
      ostream2.writeInt(bytes.length); 
      ostream2.write(bytes, 0, bytes.length); 
     } 
     long end = System.nanoTime(); 

     System.out.println("write byte[] took: " + ((end - start)/1000) + " micros"); 
    } 

    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    try(ObjectOutputStream ostream = new ObjectOutputStream(out)) { 
     for (int i = 0; i < 10000; ++i) { 
      ostream.writeObject(bytes); 
     } 

     out.reset(); 

     long start = System.nanoTime(); 
     for (int i = 0; i < 10000; ++i) { 
      ostream.writeObject(bytes); 
     } 
     long end = System.nanoTime(); 

     System.out.println("writeObject took: " + ((end - start)/1000) + " micros"); 
    } 
} 

输出

写字节[]了:15445万分之一

的writeObject了:3111万分之一

ObjectOutputStream.writeObject()节省写对象。如果你已经写过那个对象,它只会写一个句柄给同一个对象,而不是整个对象。

+0

事实上,你是正确的。我将代码替换为每次都有一个新数组,写入字节数组现在比writeObject快。我完全忘记了writeObject所做的缓存 –

我写你的代码稍加修改:

public class Test { 

    public static final int REPS = 10000; 

    public static void main(String argv[]) throws IOException { 
    ByteArrayOutputStream out2 = new ByteArrayOutputStream(); 
    try (ObjectOutputStream ostream2 = new ObjectOutputStream(out2)) { 
     writeBytes(ostream2); 
     out2.reset(); 
     long start = System.nanoTime(); 
     writeBytes(ostream2); 
     long end = System.nanoTime(); 
     System.out.println("write byte[] took: " + ((end - start)/1000) + " micros"); 
    } 

    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    try (ObjectOutputStream ostream = new ObjectOutputStream(out)) { 
     writeObject(ostream); 
     out.reset(); 
     long start = System.nanoTime(); 
     writeObject(ostream); 
     long end = System.nanoTime(); 
     System.out.println("writeObject took: " + ((end - start)/1000) + " micros"); 
    } 
    } 

    private static void writeObject(ObjectOutputStream ostream) throws IOException { 
    for (int i = 0; i < REPS; ++i) { 
     final byte[] bytes = bytes(); 
     ostream.writeObject(bytes); 
    } 
    } 

    private static void writeBytes(ObjectOutputStream ostream2) throws IOException { 
    for (int i = 0; i < REPS; ++i) { 
     final byte[] bytes = bytes(); 
     ostream2.writeInt(bytes.length); 
     ostream2.write(bytes, 0, bytes.length); 
    } 
    } 

    static byte[] bytes() { 
    byte[] bytes = new byte[REPS]; 
    for (int i = 0; i < REPS; ++i) { 
     bytes[i] = (byte) i; 
    } 
    return bytes; 
    } 
} 

现在的结果是

write byte[] took: 51697 micros 
writeObject took: 57203 micros 
+0

谢谢你的回答。的确,我完全忘记了writeObject中的缓存机制 –