2016-09-30 3 views
7

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

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

async await обязательно не создает новые потоки все время. В SO есть много вопросов, поэтому вам нужно начать поиск. –

+0

Ture, Он тянет поток от ThreadPool для выполнения оставшейся части метода. Это то, что я упомянул – Pragmatic

+0

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

ответ

3

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

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

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

Или он также экономит CPU?

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

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

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

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

Это означает, что он не потребляет процессор.

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

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

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

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

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

+0

Спасибо usr за ответ. Что вы подразумеваете под «Поэтому нет экономии переключения контекста, вызванной обработкой нескольких завершений ввода-вывода в одном коммутаторе контекста» – Pragmatic

+1

Контекстные коммутаторы могут быть сохранены, если несколько ИО инициируются без блокировки, а затем несколько IO завершаются без блокировки. Затем вам нужно всего 2 переключателя контекста для * много * IO. Это то, что экономит переключение. Но если IOs нечасто, что я утверждаю, это дело довольно часто, тогда невозможно объединить работу по инициированию и завершению в один квант времени. Код должен будет блокироваться и переключаться, пока не придет новая работа. – usr

+1

Спасибо, это имеет смысл! – Pragmatic

20

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

Вы не являетесь.

Я знаю, что, когда исполнение достигает ждать, то отпустите нить

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

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

после IO завершает

не является awaitable потребность быть операция ввода-вывода, но давайте предположим, что это.

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

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

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

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

Не могли бы они привести к ненужному переключателю контекста.

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

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

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

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

Цель ОЖИДАНИЯ состоит в (1) делают более эффективное использование дорогих рабочих потоков, позволяя рабочие процессы, чтобы стать более асинхронными , и тем самым освобождая потоки для работы в ожидании результатов с высокой задержкой и (2) сделать исходный код для асинхронных рабочих процессов похожими на исходный код для синхронных рабочих процессов.

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

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

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

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

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

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

+1

Спасибо Эрик за ваш ответ! Поэтому мы можем сказать, что мы всегда должны использовать API aync (если он доступен), независимо от того, выполняется ли он очень быстро или требуется время. Мне нужно уточнить одну точку, если есть 100 одновременных потоков (на 4-х основных машинах), процессор будет переключаться с одного потока на другой, если поток запускает IO. Или это чисто основано на временном разрезе, и вся доля получает их равную долю процессора (независимо от того, связаны ли они с привязкой или связаны с IO). Предполагая, что в этом случае используется IO API синхронизации. – Pragmatic

+0

Так уменьшается использование ЦП? Неясно из этого ответа, но это был вопрос. «Просто измерять это» - это не ответ, так как а) невозможно измерить все соответствующие сценарии, и б) он не дает никакого понимания. – usr

+3

@usr: «просто измерить его» - это действительно ответ и, безусловно, самый полезный ответ. Если у вас есть лошади, и вы хотите знать, что быстрее, то попросить кучу незнакомцев в Интернете, которые никогда не видели лошадей, гораздо менее полезно, чем гоночные лошади. –