2017-01-31 1 views
1

J'essayais de trouver un goulot d'étranglement IO dans ma classe et étonnamment remarqué que sw.Write("m"); sw.Flush() peut être 20000 plus rapide, puis await sw.WriteAsync("m"); Await sw.FlushAsync(); lors de l'écriture de 1000000 messages dans un fichier. Est-ce que, par hasard, quelqu'un sait pourquoi? Mon pari est le constructeur StreamWriter prenant un String ne pas paramétrer un flux pour l'utilisation async.StreamWriter: (Write + Flush) Async semble beaucoup plus lent puis synchrone variantes

Le code ci-dessous peut être lancé à partir de C# interactif. Oui, ce n'est pas le meilleur endroit pour mesurer la vitesse, mais il montrera la question à toute façon:

var sr = new StreamWriter("G:\\file.file"); 
var N = 1000; 
var sw = new Stopwatch(); 
sw.Start(); 

for (var i = 0; i < N; ++i) 
{ 
    sr.Write("m"); // or await sr.WriteAsync("m"); 
    sr.Flush(); // or await sr.FlushAsync("m"); 
} 

sw.Stop(); 
Console.WriteLine("Completed " + N 
    + " iterations in " + sw.ElapsedMilliseconds + " milliseconds."); 

sr.Close(); 

Lancé sur mon PC à la maison de C# Interactive la sortie est

Terminé 1000 itérations 1 millisecondes.

pour le code synchrone et

terminées 1000 itérations dans 43383 millisecondes.

pour asynchrone.

Mise à jour: J'ai aussi remarqué que le programme ralentit l'intérieur FlushAsync. WriteAsync fonctionne presque à la même vitesse que la version synchrone.

Tous les commentaires sont les bienvenus.

+0

Peut-être voir [cette réponse] (http://stackoverflow.com/a/18335900/4372746). Aussi, vous auriez sûrement attendu les deux heures pour former un poste complet? –

+0

@Glorin Oakenfoot merci pour le lien. Yeap, mon mauvais, mais j'étais inquiet que je puisse probablement l'oublier :-( –

+0

Je ne sais pas pourquoi quelqu'un utiliserait une méthode Async Write.Il ya très peu de différence entre Sync Write et Async Write. rapidement, il ne paie pas pour aller à Async – jdweng

Répondre

4

StreamWriter, lorsqu'il reçoit un chemin de fichier, n'ouvre pas son flux sous-jacent en mode asynchrone. Cela contribue probablement à la perte de performance. Si vous allez l'utiliser pour async, vous devez ouvrir votre propre Stream:

Stream s = new FileStream("G:\\file.file", FileMode.Create, FileAccess.Write, 
          FileShare.None, 4096, 
          FileOptions.Asynchronous | FileOptions.SequentialScan); 
StreamWriter sr = new StreamWriter(s); 

Quelque chose supplémentaire à noter est que votre référence ne semble pas saisir l'utilisation dans le monde réel. Etes-vous vraiment en train d'écrire des cordes à un seul caractère et de les rincer après chacune d'elles? Async a une certaine quantité fixe de mémoire et de surcharge GC, et avec de telles opérations de courte durée - d'autant plus que StreamWriter.WriteAsync n'est pas actuellement optimisé pour les petites écritures - vous devez voir beaucoup plus de frais généraux qu'un plus commun usage.

+0

J'ai essayé de créer un ' Stream 'manuellement, mais il est encore beaucoup plus lent que la version synchrone Non, je n'écris pas de chaînes de caractères simples, mais je suis en train d'écrire un court messages de journal.La mémoire/GC overhead n'est pas si important pour moi parce que d'autres constructions avec des opérations asynchrones sont appelées quelques millions de fois en une seconde et tout va bien –

+1

J'ai aussi remarqué que le vrai problème est à l'intérieur de 'FlushAs ync'.'WriteAsync' fonctionne presque à la même vitesse que la version synchrone. –

+1

'FlushAsync' sur' FileStream' est implémenté avec un faux async, malheureusement. Je m'attends à ce que ça ne fonctionne pas très bien. –