Консалтинг и автоматизация в области управления
эффективностью банковского бизнеса

Журнал ВРМ World

Реинкарнация Stackless Python

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

Манипулирование стеком выполнения - вот для чего задумывались продолжения (continuation), структурный элемент многих других неочевидных, но мощных структур программирования. На обычном Python, с его кадрами стека, напрямую соединенными со стеком С, это просто невозможно. Привязанный к стеку С Python не контролирует полностью свою цепочку выполнения. Кроме того, стек С накладывает ограничения на рекурсию. Глубина рекурсии определяется размером стека.

В статье "Предложение по улучшению Python - Stackless" (A Stackless PEP) говорилось о том, что разработчик Stackless Кристиан Тисмер (Christian Tismer) надеется, что Stackless будет принят в качестве части ядра Python. И именно это вызвало ожесточенную полемику. Ведь Python делает упор на простоту, и поэтому считалось, что такая высоко мощная технология чужда Python. А изменения, внесенные Тисмером, не стали бы работать с Jython. Они были крайне сложны, их мало кто понимал, и почти никто не желал их поддерживать. Хотя с последним утверждением, пожалуй, можно поспорить. Поддержка Stackless была для Тисмера тяжелым испытанием, и отчасти поэтому он хотел, чтобы Stackless вошел в ядро. Сторонники Stackles, рассчитывали, что, несмотря на сопротивление, он будет принят. Так, в прошлом году в своей статье "Пути Python" (A Python Roadmap) Камерон Лэрд (Cameron Laird) предсказывал, что Python 2.1 будет Stackless. Но этого не произошло

"Я пытался убедить основную группу разработчиков полностью переработать Python, разорвав эту неестественную пару, - пишет Тисмер.- Стек Python - это цепочка связанных кадров, которые могли бы легко заменять друг друга, но на их пути, подобно каменному утесу, стоит стек С, воспроизводя каждое вложение кадров Python. Из-за этого переключение было невозможно. Но не сегодня. Я снова превратил недостатки в достоинства и совершил невозможное".

После долгих размышлений над куском торта и несколькими чашками кофе, Тисмер решил оставить свой старый код, равно как и всякие надежды на то, что его примут в ядро. Вместо этого он занялся манипулированием самим стеком С. В 1999 году, когда Stackless еще не было, Сэм Рашинг (Sam Rushing) создал сопрограммный пакет, который напрямую переключал стеки С. Разработчики Python договорились, что подобное недопустимо в ядре Python. В противном случае переносить Python стало бы слишком трудно, так как каждая платформа и каждый компилятор обрабатывают стек С по-разному. Для того, чтобы быть частью Python, манипулирование стеком С было запрещено. Сложный код Stackless Тисмера был результатом его попыток сделать невозможное: не переписывая Python и даже не прикасаясь к самому стеку С, заставить продолжения работать внутри Python. Но Stackless так и не вошел в ядро. "Stackless умер. Да здравствует Stackless!"

В соответствие со своим новым подходом Тисмер перехватывает вызов функции eval_frame и перенаправляет его в функцию-обертку. При первом вызове eval_frame текущая позиция в стеке С сохраняется посредством кусочка кода на ассемблере. Это становится опорной точкой для всех последующих вызовов. Код на ассемблере затем копирует в стек и из стека. Он переносит части стека, когда стек становится слишком большим, или регулирует его при обработке другой микронити (microthread) или сопрограммы. Код ядра Python не видит всего этого. Он просто проталкивает данные в стек и выталкивает их из него, как он делал всегда, не подозревая, каким манипуляциям подвергается стек за его спиной.

Изменения, вносимые в Python, незначительны и реализуются с помощью макросов, которым не нужно меняться вместе с изменением Python или Stackless. Содержимое этих макросов хранится в единственном файле stackless.h, который Тисмер может легко поддерживать. Код на ассемблере, однако, зависит от платформы и требует ручного кодирования для каждой платформы. Тисмер уже написал код для Microsoft Windows; по его мнению, для Linux на Intel это будет просто - всего несколько синтаксических изменений для gcc. Операционная система не так важна, как процессор или компилятор. Впрочем, Тисмер не планирует переходить на другую платформу, если, конечно, ему не предоставят машину и не отплатят неделю работы.

Кое-кто опасался, что смерть Stackless может повлечь за собой кончину Python для Palm. Учитывая ограничения, накладываемые Palm на размер памяти, важно лимитировать размер стека. До сих пор Stackless являлся основой для переносов Python. Я поинтересовался у Тисмера, будет ли его новый подход работать на Palm. "Я бы сказал: еще лучше, - ответил он. - Я протестировал Stackless, ограничив требования к общему размеру стека ниже 2 килобайт. Новая технология оказалась очень удачной, так как она не требует переключения на другой аппаратный стек. Она просто увеличивает и сжимает текущий стек, как это делают обычные функции С". По его словам, перенос на Palm находится в разработке.

В настоящий момент Тисмер занялся более интересным делом - он пишет stacklessmodule.c, который определит базовые операции для сопрограмм и микронитей. Поскольку теперь в Python есть генераторы, Тисмер не будет повторно реализовывать их в Stackless и пока не будет поддерживать продолжения первого класса (first class continuations).

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


 

Стивеин Фиггенз (Stephen Figgins) руководит отделом Python DevCenter в O'Reilly Network, он также один из редакторов O'Reilly Network.