Всем известно, что асинхронность дает вам «лучшую пропускную способность», «масштабируемость» и более эффективную с точки зрения потребления ресурсов. Я также подумал об этом (упрощенно), прежде чем проводить эксперимент ниже. В основном это говорит о том, что если мы учтем все накладные расходы для асинхронного кода и сравним его с правильно настроенным синхронным кодом, это приведет к небольшим или нулевым преимуществам производительности / пропускной способности / потребления ресурсов.
Вопрос: действительно ли асинхронный код работает намного лучше по сравнению с синхронным кодом с правильно настроенным пулом потоков? Может быть, мои тесты производительности испорчены каким-то драматическим образом?
Тестовая настройка: два метода ASP.NET Web API с JMeter пытаются вызвать их с группой потоков из 200 потоков (время увеличения 30 секунд).
[HttpGet]
[Route("async")]
public async Task<string> AsyncTest()
{
await Task.Delay(_delayMs);
return "ok";
}
[HttpGet]
[Route("sync")]
public string SyncTest()
{
Thread.Sleep(_delayMs);
return "ok";
}
Вот время отклика (логарифмическая шкала). Обратите внимание, как синхронный код становится быстрее, когда в пул потоков вводится достаточно потоков Если бы мы настроили пул потоков заранее (через SetMinThreads
), он превзошел бы async
с самого начала.
А как насчет потребления ресурсов, спросите вы? «Поток имеет большую стоимость с точки зрения планирования процессорного времени, переключения контекста и использования оперативной памяти». Не так быстро. Планирование потоков и переключение контекста эффективно. Что касается использования стека, поток не сразу потребляет оперативную память, а просто резервирует виртуальное адресное пространство и выделяет только крошечную долю , которая действительно необходима.
Давайте посмотрим, что говорят данные. Даже при большем количестве потоков синхронизация имеет меньший объем памяти (рабочий набор, который отображается в физическую память).
UPDATE . Я хочу опубликовать результаты последующего эксперимента, который должен быть более репрезентативным, поскольку позволяет избежать некоторых ошибок первого.
Прежде всего, результаты первого эксперимента взяты с использованием IIS Express, который в основном является сервером времени для разработчиков, поэтому мне нужно было отойти от этого. Кроме того, учитывая отзывы, я изолировал машину для генерации нагрузки от сервера (две виртуальные машины Azure в одной сети). Я также обнаружил, что некоторые ограничения потоков IIS от трудных до невозможных нарушают, и в конечном итоге переключились на собственный хостинг ASP.NET WebAPI, чтобы также исключить IIS из переменных. Обратите внимание, что объемы памяти / время процессора в этом тесте радикально различаются, поэтому не сравнивайте числа в разных прогонах теста, поскольку настройки совершенно разные (хостинг, оборудование, настройка компьютеров). Кроме того, когда я перешел на другие машины и другое решение для хостинга, стратегия пула потоков изменилась (она стала динамичной), а скорость внедрения увеличилась.
Настройки: задержка 100 мс, 200 «пользователей» JMeter, время разгона 30 с.
Я хочу завершить эти эксперименты следующим: Да, под некоторыми конкретными
(как в лабораторных условиях) можно получить сопоставимые результаты для синхронизации и асинхронности, но в реальных случаях, когда рабочая нагрузка не может быть предсказуемой на 100%, а рабочая нагрузка неравномерна, мы неизбежно столкнемся с какими-то ограничениями потоков: либо со стороны сервера, или пределы увеличения пула потоков (и имейте в виду, что управление пулами потоков - это автоматический механизм с не всегда легко предсказуемыми свойствами). Кроме того, версия синхронизации имеет больший объем памяти (как рабочий набор, так и объем виртуальной памяти). Что касается потребления ЦП, асинхронность также выигрывает (время ЦП на показатель запроса).
В IIS с настройками по умолчанию ситуация еще более драматична: синхронная версия на порядок (и) медленнее (и меньшая пропускная способность) из-за довольно жесткого ограничения на количество потоков - 20 на CPU .
PS. Используйте асинхронные конвейеры для ввода-вывода! [ ... вздох облегчения ... ]