2009-06-08 6 views
2

Was ist schneller?
out.writeObject (someString) oder out.writeUTF (someString)Java writeObject Vs. writeUTF

+3

Sicher handhaben können Sie dies selbst heraus durch Profilierung haben könnte. –

+1

Erwähnenswert: 'writeUTF' behandelt _not_ nicht mit' null'. – nilskp

Antwort

4

Ich schrieb einen Testfall, und writeObject ist schneller. Ein möglicher Grund ist folgender: "Beachten Sie, dass ein wesentlicher Unterschied zwischen dem Schreiben eines Strings in den Stream als primitive Daten oder als Objekt besteht. Eine von writeObject geschriebene String-Instanz wird zunächst als String in den Stream geschrieben. Future writeObject() ruft write auf Verweise auf die Zeichenfolge in den Stream. " Siehe die writeObject-Dokumentation.

EDIT: Allerdings ist writeUnshared immer noch schneller als 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(); 

    } 
} 
+0

Das ist insofern überraschend, als writeObject intern prüft, ob das Objekt ein String ist, und writeUTF aufruft. –

+0

@AndrewFinnell, ja, ich bestätigte die Ergebnisse, aber ich bin mir nicht sicher warum. Sie haben Recht, dass es keine Unterscheidung nach UTF-16 v. UTF-8 gibt (writeString ruft writeUTF auf, das ist modifiziertes UTF-8). Es könnte zu einem Testartefakt werden. Ich bin mir besonders nicht sicher, warum writeUnshared schneller ist, wenn es mehr tut und doppelte Kopien schreibt. –

+1

Ist das nicht ein gutes Beispiel dafür, wie man einen Mikro-Benchmark NICHT macht? – nilskp

0

Keine Ahnung.

Zeit beide von diesen und es wird Ihnen schneller sagen, als wir können.

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

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

Dann wechseln Sie die Reihenfolge der Schleifen und staunen Sie, wie wenig Ihnen das sagt. – nilskp

1

Ich würde davon ausgehen, dass das Ergebnis auf die Inhalte der someString abhängen. Es fällt mir ein, dass es kein unangemessenes Ergebnis wäre, wenn sich die Leistung ändert, da die höheren Unicode-Punkte verwendet werden, so dass die Ausgabe Multi-Byte ist.

Bitte beachten Sie, dies ist unbewiesen und ist nur ein leerer Gedanke.

8

Es gibt zwei Dinge, die ich Menschen von dieser quesiton lernen wollen: Java Serialisierung ist langsam - damit leben. Microbenchmarks sind schlimmer als Fehler.

Mikropräparationen sind in der Regel irreführend. Es gibt einige Dinge, die es wert sind, als allgemeines Idiom ausgeführt zu werden (z. B. das Herausziehen der Schleife in C). Optimierer haben die Angewohnheit, Microbenchmarks zu brechen. Nimm deine Anwendung und profiliere sie unter Reallast. Wenn ein Programmcode Ihr Programm verlangsamt, optimieren Sie es nicht. Microbenchmarks werden Ihnen nicht helfen, diese Orte zu finden.

writeObject und writeUTF machen nicht dasselbe. writeObject gibt an, welche Art von Objekt es schreiben wird. WriteObject schreibt auch eine Zurück-Referenz, wenn das gleiche Objekt (String) seit dem letzten Zurücksetzen geschrieben wurde. writeUnshared ist näher an writeUTF.

Also, wenn Sie weiterhin genau die gleiche lange String writeObject schreiben sollte gewinnen, weil es nur eine Rückverweis schreiben muss. Die Reduzierung der serialisierten Größe kann die Datei-/Netzwerkbandbreite oder nur den Arbeitsspeicher verringern, was zu größeren Leistungsverbesserungen führen kann. Bei kurzen Strings ist das Schreiben der Daten schneller. writeUnshared sollte fast writeUTF-Leistung liefern, aber die Allgemeinheit beibehalten.

Hinweis: In allen Fällen werden Daten als UTF-8 und nicht als UTF-16 geschrieben. Wenn Sie möchten UTF-16 String.toCharArray oder ähnliches tun.

0

Mit DataOutputStrema.writeUTF() erhalten Sie eine bessere Leistung als mit ObjectOutputStream.writeUTF().

1

Sie sollten sich bewusst sein, dass writeUTF nur Strings mit einer Länge < 65535 ...