Действительно ли асинхронная модель дает преимущества в пропускной способности по сравнению с правильно настроенной синхронной? - PullRequest
10 голосов
/ 24 апреля 2019

Всем известно, что асинхронность дает вам «лучшую пропускную способность», «масштабируемость» и более эффективную с точки зрения потребления ресурсов. Я также подумал об этом (упрощенно), прежде чем проводить эксперимент ниже. В основном это говорит о том, что если мы учтем все накладные расходы для асинхронного кода и сравним его с правильно настроенным синхронным кодом, это приведет к небольшим или нулевым преимуществам производительности / пропускной способности / потребления ресурсов.

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

Тестовая настройка: два метода 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 с самого начала.

response time

А как насчет потребления ресурсов, спросите вы? «Поток имеет большую стоимость с точки зрения планирования процессорного времени, переключения контекста и использования оперативной памяти». Не так быстро. Планирование потоков и переключение контекста эффективно. Что касается использования стека, поток не сразу потребляет оперативную память, а просто резервирует виртуальное адресное пространство и выделяет только крошечную долю , которая действительно необходима.

Давайте посмотрим, что говорят данные. Даже при большем количестве потоков синхронизация имеет меньший объем памяти (рабочий набор, который отображается в физическую память).

stats-1

stats-2

UPDATE . Я хочу опубликовать результаты последующего эксперимента, который должен быть более репрезентативным, поскольку позволяет избежать некоторых ошибок первого.

Прежде всего, результаты первого эксперимента взяты с использованием IIS Express, который в основном является сервером времени для разработчиков, поэтому мне нужно было отойти от этого. Кроме того, учитывая отзывы, я изолировал машину для генерации нагрузки от сервера (две виртуальные машины Azure в одной сети). Я также обнаружил, что некоторые ограничения потоков IIS от трудных до невозможных нарушают, и в конечном итоге переключились на собственный хостинг ASP.NET WebAPI, чтобы также исключить IIS из переменных. Обратите внимание, что объемы памяти / время процессора в этом тесте радикально различаются, поэтому не сравнивайте числа в разных прогонах теста, поскольку настройки совершенно разные (хостинг, оборудование, настройка компьютеров). Кроме того, когда я перешел на другие машины и другое решение для хостинга, стратегия пула потоков изменилась (она стала динамичной), а скорость внедрения увеличилась.

Настройки: задержка 100 мс, 200 «пользователей» JMeter, время разгона 30 с.

response-time-2

stats-2-1

stats-2-2

Я хочу завершить эти эксперименты следующим: Да, под некоторыми конкретными (как в лабораторных условиях) можно получить сопоставимые результаты для синхронизации и асинхронности, но в реальных случаях, когда рабочая нагрузка не может быть предсказуемой на 100%, а рабочая нагрузка неравномерна, мы неизбежно столкнемся с какими-то ограничениями потоков: либо со стороны сервера, или пределы увеличения пула потоков (и имейте в виду, что управление пулами потоков - это автоматический механизм с не всегда легко предсказуемыми свойствами). Кроме того, версия синхронизации имеет больший объем памяти (как рабочий набор, так и объем виртуальной памяти). Что касается потребления ЦП, асинхронность также выигрывает (время ЦП на показатель запроса).

В IIS с настройками по умолчанию ситуация еще более драматична: синхронная версия на порядок (и) медленнее (и меньшая пропускная способность) из-за довольно жесткого ограничения на количество потоков - 20 на CPU .

PS. Используйте асинхронные конвейеры для ввода-вывода! [ ... вздох облегчения ... ]

Ответы [ 2 ]

3 голосов
/ 24 апреля 2019

Всем известно, что асинхронность дает вам "лучшую пропускную способность", "масштабируемость" и более эффективную с точки зрения потребления ресурсов.

Масштабируемость, да.Пропускная способность: это зависит.Каждый асинхронный запрос на медленнее , чем эквивалентный синхронный запрос, поэтому вы увидите преимущество в пропускной способности только тогда, когда вступает в силу масштабируемость (т. Е. Запросов больше, чем доступно потоков).

Асинхронный код на самом деле работает намного лучше по сравнению с синхронным кодом с правильно настроенным пулом потоков?

Что ж, подвох есть "правильно настроенный пул потоков".Вы предполагаете, что вы можете: 1) предсказать свою нагрузку и 2) иметь достаточно большой сервер, чтобы обрабатывать его, используя один поток на запрос.Для многих (большинства?) Реальных производственных сценариев один или оба из них не соответствуют действительности.

Из моей статьи об асинхронном ASP.NET :

Почему бы просто не увеличить размер пула потоков [вместо использования async]?Ответ двоякий: асинхронный код масштабируется и дальше, и быстрее, чем блокирующий потоки пула потоков.

Во-первых, асинхронный код масштабируется дальше, чем синхронный код.В более реалистичном примере кода масштабируемость серверов ASP.NET (стресс-тестирование) показала мультипликативное увеличение.Другими словами, асинхронный сервер может обрабатывать несколько раз количество непрерывных запросов как синхронный сервер (при этом оба пула потоков были максимально увеличены для этого оборудования).Однако эти эксперименты (не сделанные мной) были проведены на ожидаемой «реалистичной основе» для средних приложений ASP.NET.Я не знаю, как те же результаты переносятся в noop-строку.

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

Я думаю, что работа, которую вы проделали, интересна;Меня особенно удивляют различия в использовании памяти (точнее, отсутствие различий).Я хотел бы видеть, как вы работаете над этим в блоге.Рекомендации:

  • Используйте ASP.NET Core для своих тестов.Старый ASP.NET имел только частично асинхронный конвейер;ASP.NET Core понадобится для более «чистого» сравнения sync и async.
  • Не проверять локально;при этом много предостережений .Я бы порекомендовал выбрать размер виртуальной машины (или Docker-контейнер для одного экземпляра или любой другой) и провести тестирование в облаке на предмет повторяемости.
  • Также попробуйте стресс-тестирование в дополнение к нагрузочному тестированию.Продолжайте увеличивать нагрузку, пока сервер не будет полностью перегружен, и посмотрите, как отвечают асинхронный и синхронизирующий серверы.

В качестве последнего напоминания (также из моей статьи):

Имейте в виду, что асинхронный код не заменяет пул потоков.Это не пул потоков или асинхронный код;это пул потоков и асинхронный код.Асинхронный код позволяет вашему приложению оптимально использовать пул потоков.Он берет существующий пул потоков и увеличивает его до 11.

1 голос
/ 24 апреля 2019

Абсолютно асинхронный код (I / O) более масштабируем, поскольку он освобождает потоки пула потоков для другой работы, а не блокирует их.Таким образом, при том же количестве потоков он может обрабатывать больше запросов.

Но это происходит за счет большего количества структур управления данными и большей работы.Таким образом, (кроме сохранения потоков пула потоков) он потребляет больше ресурсов (память, процессор).

Все дело в доступности, а не в производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...