Лучше ли опросить или подождать?

Я видел вопрос о том, почему "опрос плохой". С точки зрения минимизации количества процессорного времени, используемого одним потоком, было бы лучше сделать ожидание вращения (т.е. Опрос для требуемого изменения в цикле while) или дождаться объекта ядра (например, объект событий ядра в окнах)

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

Поскольку ОС, скорее всего, будет более эффективно "опросить" в случае "ожидания", я не хочу видеть, что аргумент "ожидание просто означает, что кто-то еще делает опрос", эти старые новости, и не обязательно Точность 100%.

Ответ 1

Если ОС имеет разумные реализации этих типов примитивов concurrency, определенно лучше подождать объекта ядра.

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

Вы специально спросили о минимизации времени процессора для потока: в этом примере блокировка потока на объекте ядра будет использовать время ZERO; поток опроса будет использовать все виды времени.

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

Ответ 2

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

Ответ 3

Я думаю, что еще не был поднят вопрос, что если ваша ОС должна много работать, блокируя вашу нить в другом процессе. Если все процессы используют блокирующие примитивы, где они должны (например, ядро ​​ждет, файл/сеть IO и т.д.), Вы даете ядру больше информации, чтобы выбрать, какие потоки должны выполняться. Таким образом, он будет делать больше работы за один и тот же промежуток времени. Если ваше приложение может делать что-то полезное, ожидая, когда этот файл откроется или пакет будет отправлен, вы можете даже помочь своему собственному приложению.

Ответ 4

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

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

Ответ 5

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

Ответ 6

Я согласен с Darksquid, если ваша ОС имеет приличные примитивы concurrency, тогда вам не нужно будет опроса. опрос обычно входит в него в системах реального времени или в ограниченном аппаратном обеспечении, у которого нет ОС, тогда вам нужно опросить, потому что у вас может не быть возможности ждать(), но также потому, что он дает вам контроль за точной настройкой того, как долго вы хотите подождать в определенном состоянии, а не быть во власти планировщика.

Ответ 7

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

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

Опрос обычно не используется в ядрах ОС для реализации системных вызовов блокировки - вместо этого события (прерывания, таймеры, действия по мьютексам) приводят к блокировке процесса или потока, выполняемого runnable.

Ответ 8

Существует четыре основных подхода:

  • Используйте предварительный примитив ожидающих ОС, чтобы дождаться события
  • Используйте некоторый примитив таймера ОС, чтобы проверить с определенной скоростью, произошло ли событие
  • Неоднократно проверяйте, произошло ли событие, но используйте примитив ОС, чтобы получить временной срез для произвольной и неизвестной продолжительности в любое время.
  • Неоднократно проверяйте, произошло ли событие, не уступая CPU, если оно не было.

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

Подход № 3 довольно груб, но во многих случаях может быть хорошим. Он часто будет тратить больше времени и ресурсов процессора, чем подходит к № 1, но во многих случаях это будет проще реализовать, а отходы ресурсов во многих случаях будут достаточно малы, чтобы не иметь значения.

Подход # 2 часто сложнее, чем # 3, но имеет то преимущество, что способен обрабатывать множество ресурсов с помощью одного таймера и не выделенного потока.

Подход №4 иногда необходим во встроенных системах, но, как правило, очень плох, если нет прямого опроса аппаратного обеспечения, и у него не будет ничего полезного, пока это событие не произойдет. Во многих случаях не будет возможно, чтобы условие ожидалось, пока поток, ожидающий его, не даст CPU. Уступка процессора, как и в подходе №3, фактически позволит ожидающему потоку видеть событие раньше, чем его засовывает.