2009-06-08 14 views
2

Qu'est-ce qui est le plus rapide?
out.writeObject (someString) ou out.writeUTF (someString)Java writeObject Vs. writeUTF

+3

vous pourriez sûrement compris vous-même par le profilage. –

+1

Il convient de mentionner: 'writeUTF' ne gère pas 'null'. – nilskp

Répondre

4

J'ai écrit un scénario de test, et writeObject est plus rapide. Une raison possible est que "Notez qu'il existe une différence significative entre l'écriture d'une chaîne dans le flux en tant que données primitives ou en tant qu'objet.Une instance String écrite par writeObject est écrite dans le flux en tant que chaîne au début.Appels futurs writeObject() références à la chaîne dans le flux. " Voir la documentation writeObject.

EDIT: Cependant, writeUnshared est encore plus rapide que 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

Cela est plutôt surprenant vu que writeObject vérifie en interne que l'objet est un String, puis appelle writeUTF. –

+0

@AndrewFinnell, oui, j'ai confirmé les résultats, mais je ne sais pas pourquoi. Vous avez raison, il n'y a pas de distinction UTF-16 v. UTF-8 (writeString appelle writeUTF, qui est modifié UTF-8). Cela pourrait finir par être un artefact de test. Je ne suis pas particulièrement sûr pourquoi writeUnshared est plus rapide quand il fait plus et écrit des copies. –

+1

N'est-ce pas un bon exemple de comment ne pas faire un micro-benchmark? – nilskp

0

Aucune idée.

Temps de ces deux et il vous dira plus vite que nous pouvons.

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

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

Ensuite, changez l'ordre des boucles et soyez surpris du peu que cela vous indique. – nilskp

1

Je suppose que le résultat peut dépendre du contenu de someString. Il me semble que ce ne serait pas un résultat déraisonnable de constater que writeUTF changements de performance que les points unicode supérieurs sont utilisés de telle sorte que la sortie est multi-octets.

S'il vous plaît noter que ce n'est pas prouvé et est juste une pensée oisive.

8

Il y a deux choses que je veux que les gens à apprendre de cette quesiton: sérialisation Java est lent - vivre avec elle. Les microbenchmarks sont pires que les échecs.

Les micro-marques ont tendance à être trompeuses. Il y a des choses qui valent la peine d'être considérées comme un idiome général (par exemple, hisser strlen hors de la boucle en C). Les optimiseurs ont l'habitude de casser les microbenchmarks. Prenez votre application et le profil sous charge réelle. Si un morceau de code ralentit votre programme, ne vous embêtez pas pour l'optimiser. Microbenchmarks ne vous aidera pas à trouver ces endroits. WriteObject et writeUTF ne font pas la même chose.

writeObject indique quel type d'objet il va écrire. En outre, writeObject écrit simplement une référence arrière si le même objet (chaîne) a été écrit depuis la dernière réinitialisation. writeUnshared est plus proche de writeUTF. Par conséquent, si vous continuez à écrire exactement la même chaîne longue, writeObject devrait gagner car il lui suffit d'écrire une référence arrière. La réduction de la taille sérialisée peut réduire la bande passante du fichier/réseau ou simplement la mémoire, ce qui peut entraîner des améliorations de performances plus importantes. Pour les chaînes courtes, il suffit d'écrire les données plus rapidement. writeUnshared devrait donner presque des performances en écriture, mais en maintenant la généralité.

Notez, dans tous les cas, que les données sont écrites en UTF-8 et non en UTF-16. Si vous voulez UTF-16 String.toCharArray ou similaire fera l'affaire.

0

Vous obtiendrez de meilleures performances avec DataOutputStrema.writeUTF() qu'avec ObjectOutputStream.writeUTF().

1

Vous devez être conscient que writeUTF ne peut gérer les chaînes avec une longueur < 65535 ...