Async await увеличивает переключение контекста

Я знаю, как работает async await. Я знаю, что когда выполнение достигает ожидания, он освобождает поток и после завершения ввода-вывода извлекает поток из threadpool и запускает оставшийся код. Таким образом потоки не эффективно. Но я смущен в некоторых случаях использования:

  1. должны ли мы использовать асинхронные методы для очень быстрого метода ввода-вывода, например, метод чтения/записи кэша? Не приведут ли они к ненужному переключению контекста. Если мы используем метод sync, выполнение завершится на том же потоке и контекстном переключателе может не произойти.
  2. Async-await сохраняет только потребление памяти (путем создания меньших потоков). Или он также экономит cpu? Насколько я знаю, в случае синхронизации IO, в то время как IO происходит, поток переходит в спящий режим. Это означает, что он не потребляет ЦП. Правильно ли это понимание?

2 ответов


следует ли использовать асинхронные методы для очень быстрого метода ввода-вывода, например метод чтения/записи кэша?

такой IO не будет блокировать в классическом смысле. "Блокировка" - это неопределенный термин. Обычно это означает, что CPU должен ждать аппаратного обеспечения.

этот тип ввода-вывода-это чисто работа процессора, и нет никаких контекстных переключателей. Это обычно происходит, если приложение читает файл или сокет медленнее, чем данные могут быть предоставлены. Здесь async IO не помогает работы на всех. Я даже не уверен, что было бы целесообразно разблокировать поток пользовательского интерфейса, так как все задачи могут выполняться синхронно.

или он также сохраняет cpu?

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

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

вот почему использование ЦП обычно увеличивается (немного), за исключением случаев, когда машина очень высока при загрузке ЦП, и рабочие очереди часто способны доставка нового товара немедленно.

на сервере асинхронный ввод-вывод в основном полезен для сохранения потоков. Если у вас есть достаточно потоков вы поймете, нулевой или отрицательной прибыли. В частности, ни один IO не станет на один бит быстрее.

это означает, что он не потребляет cpu.

было бы пустой тратой оставить процессор недоступным во время ввода-вывода. Для ядра IO-это просто структура данных. Пока это продолжается, нет ... ЦП работу.

анонимный человек сказал:

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

перемещение одной и той же работы в другой поток, безусловно, не помогает с пропускной способностью. Это добавил работы, не снижается. Это игра в ракушки. (И async IO не использует поток во время его работы, поэтому все это основано на false предположение.)

простой способ убедить себя, что async IO обычно стоит больше CPU, чем sync IO, - это запустить простую синхронизацию и асинхронность TCP Ping/pong. Синхронизация быстрее. Это своего рода искусственная нагрузка, поэтому это просто намек на то, что происходит, а не всеобъемлющее измерение.


Я знаю, как работает async await.

вы не.

Я знаю, что когда выполнение достигает ожидания, оно освобождает поток

Это не так. Когда выполнение достигает ожидания, ожидаемый операнд вычисляется, а затем проверяется, завершена ли операция. Если это не так, то остальная часть метода подписывается как продолжение ожидаемого и задача, представляющая работу текущий метод возвращается вызывающему объекту.

ничто из этого не является "освобождением потока". Скорее,управление возвращается вызывающему, и вызывающий продолжает выполняться в текущем потоке. Конечно, если текущий вызывающий абонент был единственным в этом потоке, то поток выполнен. Но нет требования, чтобы асинхронный метод был единственным вызовом в потоке!

после завершения ввода-вывода

ожидаемый не должен быть IO операции, но предположим, что это так.

он извлекает поток из threadpool и запускает оставшийся код.

нет. Это планирует оставшийся код для запуска в правильном контексте. Этот контекст может быть нитью threadpool. Это может быть поток пользовательского интерфейса. Это может быть текущий поток. Это может быть что угодно.

должны ли мы использовать асинхронные методы для очень быстрого метода ввода-вывода, например cache метод чтения / записи?

ожидаемый вычисляется. Если ожидающий знает, что он может завершить операцию за разумное количество времени, то он имеет полное право выполнить операцию и вернуть выполненную задачу. В этом случае штрафа нет; вы просто проверяете логическое значение, чтобы увидеть, завершена ли задача.

не приведут ли они к ненужному переключению контекста.

Не обязательно.

Если мы используем метод синхронизации, выполнение завершится в том же потоке, и контекстный переключатель может не произойти.

Я смущен, почему вы думаете, что контекстный переключатель происходит при операции ввода-вывода. Операции ввода-вывода выполняются на оборудовании ниже уровня потоков ОС. Там нет потока, сидящего там, обслуживающего задачи ввода-вывода.

Async-await сохраняет только потребление памяти (путем создания меньших потоков)

цель await- (1) сделать больше эффективное использование дорогостоящих рабочих потоков, позволяя рабочим процессам становиться более асинхронными и тем самым освобождая потоки для работы в ожидании результатов с высокой задержкой, и (2) сделать исходный код для асинхронных рабочих процессов похожим на исходный код для синхронных рабочих процессов.

насколько я знаю, в случае синхронизации IO, в то время как IO происходит, поток переходит в спящий режим. Это означает, что он не потребляет ЦП. Это понимание правильно?

конечно, но у вас это полностью назад. ВЫ ХОТИТЕ ПОТРЕБЛЯТЬ CPU. Вы хотите потреблять как можно больше процессора, как это возможно все время! Процессор делает работа от имени пользователей и если это ожидания тогда он не делает свою работу так быстро, как мог. Не нанимайте рабочих и не платите им за сон! Наймите работника, и как только они будут заблокированы на задаче с высокой задержкой,поставить их работать, делая что-то другое таким образом, процессор остается как можно более горячим все время. Владелец этой машины заплатил хорошие деньги за этот процессор; он должен работать на 100% все время, когда есть работа!

Итак, вернемся к вашему фундаментальному вопросу:

ожидает ли async увеличения переключения контекста

Я знаю отличный способ узнать. Напишите программу с помощью await, напишите другую без, запустить их оба!--14-->, и измерить количество переключений контекста в секунду. Тогда ты узнаешь.

но я не понимаю, почему переключение контекста в секунду-это соответствующие метрики. Давайте рассмотрим два банка с большим количеством клиентов и большим количеством сотрудников. В банке № 1 сотрудники работают над одной задачей, пока она не будет выполнена; они никогда не меняют контекст. Если сотрудник заблокирован в ожидании результата от другого, он засыпает. В банке № 2 сотрудники при блокировке переходят с одной задачи на другую, и постоянно обслуживаем запросы клиентов. Как вы думаете, какой банк быстрее обслуживает клиентов?