Планировщик ОС
В этой теме мы разберем:
-
Что такое планировщик ОС и для чего он нужен.
-
Какие могут быть состояния у потока и как он работает.
-
Алгоритм поиска баланса.
-
Что такое линии кэша и ложный обмен.
-
Сценарий решения о планировании.
Дизайн и поведение планировщика Go позволяют многопоточным программам Go быть более эффективными и производительными. Это происходит благодаря механическим симпатиям планировщика Go к планировщику операционной системы (ОС). Однако если дизайн и поведение многопоточного программного обеспечения Go механически не соответствуют тому, как работают планировщики, все это не имеет значения. Важно иметь общее и репрезентативное представление о том, как работают планировщики ОС и Go, чтобы правильно проектировать многопоточное программное обеспечение.
Далее мы подробнее рассмотрим механику и семантику планировщиков более высокого уровня. Несмотря на то, что инженерные решения, которые тебе предстоит принимать во время работы над многопоточными приложениями, включают в себя многое, механика и семантика составляют важнейшую часть базовых знаний, которые тебе нужны.
Планировщик ОС
Планировщики операционной системы представляют собой сложные части программного обеспечения. Они должны учитывать компоновку и настройку оборудования, на котором работают. Это включает, но не ограничивается наличием нескольких процессоров и ядер, кэшей ЦП и NUMA. Без этих знаний планировщик не может быть максимально эффективным. Что замечательно, так это то, что ты все еще можешь разработать хорошую мысленную модель того, как работает планировщик ОС, не углубляясь в эти темы!
Твоя программа — это всего лишь набор машинных инструкций, которые нужно последовательно выполнять одну за другой. Чтобы это произошло, операционная система использует концепцию потока. Задача потока — учитывать и последовательно выполнять назначенный ему набор инструкций. Выполнение продолжается до тех пор, пока не останется инструкций для выполнения потока.
Каждая программа, которую ты запускаешь, создает процесс, и каждому процессу присваивается начальный поток. Потоки имеют возможность создавать больше потоков. Все эти разные потоки выполняются независимо друг от друга, и решения о планировании принимаются на уровне потока, а не на уровне процесса. Потоки могут выполняться:
-
одновременно (каждый из них работает на отдельном ядре);
-
параллельно (каждый из них выполняется одновременно на разных ядрах).
Потоки также сохраняют свое собственное состояние, чтобы обеспечить безопасное, локальное и независимое выполнение своих инструкций.
Планировщик ОС отвечает за то, чтобы ядра не простаивали, если есть потоки, которые могут выполняться. Это также должно создавать иллюзию того, что все потоки, которые могут выполняться, выполняются одновременно. В процессе создания этой иллюзии планировщик должен запускать потоки с более высоким приоритетом по сравнению с потоками с более низким приоритетом. Однако потоки с более низким приоритетом не могут испытывать недостаток времени выполнения. Планировщик также должен максимально минимизировать задержки планирования, принимая быстрые и разумные решения.
Для того, чтобы это произошло, многое нужно для алгоритмов. Чтобы лучше понять это, полезно рассмотреть несколько важных концепций.