2017-01-31 41 views
1

Я пытался найти узкое место в моем классе и удивительно заметил, что sw.Write("m"); sw.Flush() может быть на 20000 быстрее, чем await sw.WriteAsync("m"); Await sw.FlushAsync(); при записи 1000000 сообщений в файл. Неужели кто-нибудь знает, почему? Моя ставка - . Конструктор, принимающий String, не параметризует поток для использования async.StreamWriter: (Write + Flush) Async кажется намного медленнее, чем синхронные варианты

Этот код может быть запуститься c интерактивным C#. Да, это не самое лучшее место для измерения скорости, но он будет показывать этот вопрос под рукой в ​​любом случае:

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(); 

Запущенный на моем домашнем ПК с C# Interactive выход

Заполненные 1000 итераций в 1 миллисекунды.

для синхронного кода и

Заполненные 1000 итераций в 43383 миллисекунд.

для асинхронного использования.

Update: Кроме того, я заметил, что программа замедляет внутри FlushAsync. WriteAsync работает почти с той же скоростью, что и синхронная версия.

Все комментарии могут быть отправлены.

+0

Возможно увидеть [этот ответ] (http://stackoverflow.com/a/18335900/4372746). Кроме того, наверняка вы могли бы просто подождать два часа, чтобы сформировать полный пост? –

+0

@ Glorin Oakenfoot спасибо за ссылку. Yeap, мой плохой, но я был обеспокоен тем, что я, вероятно, могу его забыть :-( –

+0

Я не знаю, почему кто-нибудь будет использовать метод Async Write. Между записью Sync Write и Async Write очень мало различий. быстро он не платит, чтобы перейти к Async. – jdweng

ответ

4

StreamWriter, когда задан путь к файлу, не открывается его базовый поток в асинхронном режиме. Это, вероятно, способствует снижению производительности. Если вы собираетесь использовать его для асинхронного, вы должны открывать свои собственный Stream:

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

что-то дополнительное, чтобы отметить, что ваш тест не кажется, чтобы захватить реальное использование. Вы действительно пишете односимвольные строки и заливаете их после каждого из них?

Async имеет определенный фиксированный объем памяти и накладные расходы на GC и с такими краткосрочными операциями, особенно, поскольку StreamWriter.WriteAsync в настоящее время не оптимизирован для небольших операций записи - вы должны будете видеть гораздо больше накладных расходов, чем более распространенные Применение.

+0

Я попытался создать ' Stream' вручную, но он все еще намного медленнее, чем синхронная версия. Нет, я не пишу ни одной символьной строки, но я пишу короткие сообщения журнала. Также накладные расходы памяти/GC не так важны для меня, потому что другие конструкции с асинхронными операциями называют несколько миллионов раз в секунду, и все в порядке. –

+1

Также я заметил, что настоящая проблема находится внутри 'FlushAs ync'.'WriteAsync' работает почти с той же скоростью, что и синхронная версия. –

+1

'FlushAsync' на' FileStream' реализован с фальшивой асинхронностью, к сожалению. Я ожидаю, что он не будет работать очень хорошо. –