Что именно делает процесс Erlang, зеленую нить, сопрограмму "легче", чем нить ядра? Как насчет переключения контекста это тяжело?
Возможный дубликат:
Технически, почему процессы в Erlang более эффективны, чем потоки ОС?
Каждый раз, когда упоминаются процессы Эрланга, зеленые нити или сопрограммы, они всегда описываются как "легкие" по сравнению с потоками ядра. Обычно причина заключается в том, что потоки ядра требуют медленного переключения контекста.
Но как быть с медленным переключением контекста? И насколько медленнее это по сравнению с переключением зеленых потоков в пользовательском пространстве?
Является ли переключение контекста основным (единственным?) Фактором, который объясняет разницу в производительности и потреблении памяти между управляемой событиями программой, такой как Nignx, и программой мультиобработки, такой как Apache?
1 ответ
Переключение контекста в вытесняющих, монолитных, многозадачных операционных системах включает один из двух путей: либо неявный выход для планировщика через некоторый системный вызов службы (режим ожидания, мьютекс, ожидание события, блокировка ввода / вывода), либо через прерывание и планировщик решает поменять местами запущенные задачи.
Когда планировщик меняет задачу, происходит несколько тяжелых событий:
- Все действия происходят как часть ядра операционной системы, работающей с высоким уровнем привилегий. Каждое действие проверяется (или должно быть), чтобы убедиться, что решения, принимаемые планировщиком, не предоставляют задаче никаких дополнительных привилегий (например, локальный эксплойт root)
- Адресные пространства процесса пользовательского режима меняются местами. Это приводит к тому, что менеджер памяти работает с макетами таблицы страниц и загружает новую базу каталогов в управляющий регистр.
- Это также означает, что данные, хранящиеся в кэше ЦП, могут быть удалены и удалены. Это было бы плохо, если бы ваша задача только что получила доступ к куче часто используемых вещей, тогда контекст переключился и "потерял" ее (при следующем доступе [вероятно] придется снова извлечь из основной памяти)
- В зависимости от того, как вы перехватываете ядро, вам нужно перехватывать OUT ядра. Например, если вы выполните системный вызов, ЦП выполнит очень точный набор шагов, чтобы перейти к коду, работающему в ядре, а затем при выходе отмотать эти шаги. Эти шаги сложнее, чем вызов функции для другого модуля в вашей программе, поэтому они занимают больше времени.
Насколько я понимаю, задача "зеленой нити" довольно проста. Диспетчер пользовательского режима направляет сопрограмму для запуска, пока сопрограмма не уступит. Несколько отличий в приведенном выше:
- Ни одна из процедур сопрограмм не происходит в режиме ядра, так как при отправке зеленых потоков обычно не требуется задействовать какие-либо службы операционной системы или какие-либо блокирующие службы операционной системы. Так что все это может происходить без каких-либо переключений контекста или какого-либо перевода пользователя / ядра.
- Зеленый поток не имеет приоритетного планирования или даже не вытесняется менеджером зеленых потоков, они планируются совместно. Это хорошо и плохо, но с хорошо написанными процедурами, как правило, хорошо. Каждая задача выполняет именно то, что ей нужно, а затем отправляет ее обратно диспетчеру, но без каких-либо перестановок контекста.
- Зеленые потоки делят свое адресное пространство (насколько я знаю). При переключении контекста переключение адресного пространства не происходит. Стеки (насколько я знаю) меняются местами, но эти стеки управляются диспетчером, и обмен местами также является простой записью в регистр. Обмен стека также является непривилегированной операцией.
Короче говоря, переключение контекста в пользовательском режиме включает несколько библиотечных вызовов и запись в регистр указателя стека. Переключение контекста в режиме ядра включает в себя прерывания, переход пользователя / ядра и поведение на уровне системы, такое как изменения состояния адресного пространства и сброс кеша.