Как работают озелени? - программирование
Подтвердить что ты не робот

Как работают озелени?

Как реализованы greenlets? Python использует стек C для интерпретатора, а heap - выделяет фреймы стека Python, но помимо этого, как он выделяет/свопирует стеки, как он подключается к механизмам интерпретатора и функции, и как это взаимодействует с расширениями C? (Любые причуды)?

Есть некоторые комментарии в верхней части greenlet.c в источнике, но они немного непрозрачны. FWIW Я исхожу из перспективы того, кто не знаком с внутренними компонентами CPython, но хорошо знаком с низкоуровневым системным программированием, C, потоками, событиями, сопрограммами/совместными потоками, программированием ядра и т.д.

(Некоторые точки данных: они не используют ucontext.h, и они делать 2x memcpy, выделять и свободно на каждом переключателе контекста.)

4b9b3361

Ответ 1

Когда запускается программа python, у вас есть по существу две части кода, запущенные под капотом.

Сначала выполняется код C интерпретатора CPython и используется стандартный C-стежок для сохранения его внутренних стековых кадров. Во-вторых, фактический python интерпретирует байт-код, который не использует C-стек, а использует кучу для сохранения своих стековых кадров. Геллет - это просто стандартный код python и, следовательно, ведет себя одинаково.

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

Как вы знаете, есть три фундаментальных события с зелеными, икру, переключателем и возвратом, поэтому давайте посмотрим на них:

A) Спаун

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

B) Переключатель

Когда зеленая панель переключается с зеленой коммутационной панели, соответствующая часть C-стека (начиная с базового адреса коммутационной панели) копируется в кучу. Скопированная область C-стека освобождается, а ранее сохраненный файл стека переключается с кучи на недавно освобожденную область C-стека. Код python коммутируемой окушки продолжает использовать кучу обычным способом. Разумеется, код расширения отслеживает все это (какая секция кучи подходит к какой-либо розе и т.д.).

C) Возврат

Стек не тронут, а область кучи возвращающейся окуты освобождается сборщиком мусора python.

В сущности, это гораздо больше подробностей и объяснений можно найти на (http://www.stackless.com/pipermail/stackless-dev/2004-March/000022.html) или просто прочитав код, как указано в ответе Алекса.

Ответ 2

Если вы получите и изучите источники greenlet , вы увидите в верхней части greenlet.c длинный комментарий, который начинается с строки 16 с следующее резюме...:

A PyGreenlet - это набор стеков C адреса, которые необходимо сохранить и восстановлен таким образом, что полный диапазон стека содержит достоверные данные когда мы переключимся на него.

и продолжает строку 82, в которой точно указано, о чем вы спрашиваете. Изучали ли вы эти строки (и следующие 1000+ их реализации; -)...? Я не вижу возможности дальнейшего сжимания этих 66 строк вниз, все еще имея смысл, и никакой дополнительной ценности для копирования и вставки их здесь.

В принципе, вы увидите, что нет реального "зацепления", о котором можно говорить (например, стеки уровня C переключаются туда и обратно "под носом интерпретатора" ), за исключением тонких взаимодействий с состоянием потока в мульти -пороговый код, а сохранение и восстановление состояния greenlet из/в стек основано на вызовах memcpy плюс некоторые вызовы диспетчеру памяти Python для распределения/перераспределения и свободного пространства, исходящего из стека или обратно, Три функции в строке 227-295 обрабатывают работу grunt, и они завернуты в пару макросов C на 298-310 ", чтобы упростить обслуживание", как говорится в комментарии.

Интерфейс, через который другие C-расширения могут взаимодействовать с расширением greenlet, реализуется в строках 956-1045 и просматривается через "API-интерфейс CObject" (через greenlet.h, конечно), документированный здесь.