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

Журнал ВРМ World

Stackless Pyton

Игра со множеством игроков

Действие вокруг Stackless Python разворачивается так стремительно, что случайному наблюдателю трудно уследить за ходом событий. Для понимания Stackless Python полезно вспомнить основных действующих лиц:

Мелвин Е. Конвей (Melvin E. Conway) - автор исходной публикации по сопрограммам, увидевшей свет в 1963 г.

Майк Флетчер (Mike Fletcher) - автор общей системы виртуальной реальности, основанной на микронитях (microthreads).

Стивен Мэжевски (Steven Majewski)- состоит в штате отдела медико-молекулярной физиологии в Университете штата Вирджиния. Внес значительный вклад на начальном этапе разработки языка Python. Занимался анализом генераторов, последовательностей и сопрограмм в языке Python, в середине 90х годов.

Гордон МакМиллан (Gordon McMillan) - автор связанных со Stackless Python предложений по расширению языка Python. Независимый консультант, "активно использующий Stackless Python с мая 2000 г." в промышленных приложениях, основанных на сопрограммах.

Тим Петерс (Tim Peters) - давно работает с языком Python и участвует в разработке. Недавно нанят PythonLabs.com для своей первой оплачиваемой работы с Python за всю свою карьеру. Глубоко разбирается в абстрактных понятиях языка. Считает продолжения (continuations) наиболее правильным обобщением сопрограм. Автор статьи о сопрограммах на языке Python, опубликованной в 1994 году.

Сэм Рашинг (Sam Rushing) - независимый консультант. Предпочитает использовать в работе сопрограммы в основном для "массивных параллельных" систем сообщений, частично финансируемых eGroups. Источник исходного вдохновения Тимера.

Кристиан Тисмер (Christian Tismer)- независимый консультант. Изобретатель Stackless Python.

Гвидо ван Россум (Guido van Rossum) - изобретатель Python. Подозрительно относится к Stackless Python. В последнее время является в BeOpen руководителем PythonLabs.com.

Джаст ван Россум (Just van Rossum) - Издатель. Соавтор реализации микронитей. Энтузиаст Stackless Python. Брат Гвидо ван Россума.

Уилл Уэр (Will Ware) - программист и дизайнер в Xionics Document Technologies, хорошо знаком как с аппаратными, так и с большими программными проектами.

Вы хотите, чтобы ваш любимый язык был меньше, быстрее, гибче и надежнее? Эти цели и ставил перед собой разработчик Stackless Python.

Stackless Python представляет собой альтернативную реализацию языка Python, созданную независимым разработчиком Кристианом Тисмером (Christian Tismer). Он начал со стандартного языкового процессора, разработанного изобретателем языка Гвидо ван Россумом (Guido van Rossum), и заменил на свое собственное изобретение Stackless маленькую, но одну из самых важных деталей реализации языка Python. В результате получился Stackless Python. Эта статья представляет вашему вниманию технологический подход Тисмера и отражает его значение.

Почему Stackless

Как и в случае других интереснейших технологий, путешественники по дорогам Stackless Python доносят до нас отдельные, но весьма тесно связанные между собой истории. Они обладают самыми разными знаниями и интересами. Тем не менее, они объединились. Колонка справа показывает, насколько различны были идеи, выдвинутые в течение одного десятилетия, и нашедшие свою реализацию в Stackless Python.

Главным героем этой истории является Тисмер. Он создал Stackless Python, поскольку хотел узнать, сможет ли он сделать нечто, "показавшееся невозможным" на тот момент, когда он впервые услышал об этом. Эта мысль пришла ему в голову впервые при прочтении конференции разработчиков на Python, обсуждающих технические вопросы его реализации. В той конференции в начале 1999 года Сэм Рашинг и другие отмечали, что текущая реализация языка Python недостаточно хорошо поддерживает сопрограммы. Сопрограммы - это параллельная конструкция, то есть модель для обслуживания вычислений, которые могут выполняться параллельно другим процессам, осуществляемым компьютером. Потоки задач и событий являются альтернативными формулировками параллельности или многопроцессорной обработки. Python, аналогично Java и другим языкам, напрямую поддерживает многонитевую модель.

Тем не менее, сопрограммы считаются более надежными, чем нити, так как они проще в использовании. В 1963 году Мелвин Е. Конвэй представил сопрограммы для симметричных вычислений, в которых каждая сопрограмма работает с одним и тем же "рангом". Это резко отличается от нашего обычного кодирования процедур, в котором один метод вызывает другие. Такие языки, как SIMULA и Modula, активно используют сопрограммы, а специальные библиотеки делают сопрограммы доступными для языков Си++ и Java.

Рашинг столкнулся с ограничениями реализации Python, когда ему пришлось разбираться с механизмом хранения информации, который использовал интерпретатор Python для передачи управления от одного метода другому. Стандартная реализация интерпретатора объединяет:

  • информацию о состоянии интерпретатора и
  • информацию о коде, который интерпретатор выполняет в данный момент в одном стеке.

Такой подход упрощал работу на начальном этапе развития языка, однако это затрудняло разработку параллельных алгоритмов. Еще до экспериментов Рашинга программисты несколько раз наталкивались на эти ограничения, как это было, например, когда в середине 90х годов Стивен Мэйджевски работал над "генераторами", близкими родственниками сопрограмм. Генераторы и микронити, как исходно имеющие многонитевую структуру, получили наибольшее развитие в Stackless Python.

Введение продолжений

При описании проблемы Рашинг и Тим Петерс выделяли понятие продолжения (continuation). Продолжение может рассматриваться как фундаментальное понятие в параллельных задачах. Генераторы, сопрограммы, нити и т.д. - имеют четкое определение в терминах продолжений.

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

Тисмер представил доклад "Продолжения и Stackless Python" на Восьмой Международной Конференции по языку Python сразу после наступления Нового Года 2000. У него в руках были патчи, снимающие ограничения, присущие стандартной реализации стека, и он собирался предложить Stackless Python тем, кто хотел бы его использовать.

Структура Stackless Python

Помните, что термин "Stackless Python" имеет различное значение для разных людей. Для Тисмера Stackless Python является вопросом реализации или внутренней структуры. Изменив "всего лишь малое число модулей Си", он разъединил стек языка и стек Си. Это было сделано и теперь этим можно пользоваться.

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

Stackless Python лета 2000 г. имеет немного другой интерфейс для межъязыкового взаимодействия, отличный от стандартного интерфейса Python. Ряд многоязычных проектов не позволят Stackless Python так просто стать заменой стандартному языку. Одной из задач Тисмера является изменение внутреннего содержания Stackless Python таким образом, чтобы он в большей степени отвечал требованиям таких проектов.

Тисмер занят также поиском абстракций, лучше поддерживающих сложные высокоуровневые конструкции - такие, как сопрограммы. Должна ли поддержка сопрограмм реализовываться над продолжениями или она должна быть в виде "независимого" интерфейса? Какое определение сопрограмм точнее подходит к стилю языка Python?

Кроме того, Stackless Python важен сам по себе, как альтернативная реализация. Стандартный Python ограничивает глубину рекурсии, так как хранит много информации в стеке. Сложные приложения с большой глубиной вложенности вызовов или рекурсией могут просто переполнять стек. В этом смысле Stackless Python имеет гораздо меньше ограничений, поскольку почти вся статическая информация о состоянии интерпретатора содержится в куче. Помимо этого, скорость выполнения параллельных алгоритмов, использующих возможности Stackless Python, в три раза превышает скорость соответствующих кодов Python для многонитевой реализации. Изменение реализации повлекло за собой ряд последствий. Главным интерфейсом программирования, представленным Тисмером до сего момента, стал модуль continuation. Несмотря на то, что он был признан слишком малопонятным для разработчиков приложений на Python, continuation вполне подходит в качестве рабочего блока таким системным программистам, как Гордон МакМиллан и Уилл Уэр. На базе continuation они разработали новые примитивы параллельности, которые, как оказалось, работают лучше нитей, и, к тому же, проще для понимания. Такие исследования, проводившиеся в течение всего 2000 года, оказались настолько успешными, что несколько промышленных приложений уже используют их.

Когда Тисмер говорит о Stackless Python, он главным образом думает о ядре интерпретатора Python и об улучшении его архитектуры. Это делает возможным создание новых управляющих структур, которые интересны МакМиллану и Рашингу. Их модули, написанные на Python, в свою очередь, предоставляют сопрограммы, микронити и другие высокоуровневые модели параллельного выполнения, касающиеся проблем прикладного программирования.

Микронити

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

Микронити - прекрасный ответ. В качестве соавтора их описания, Уэр утверждает:


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

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

Какое же отношение имеют эти преимущества к деталям реализации Stackless Python? Вот краткое описание:

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

Тисмер любит приводить пример, приписываемый им Джереми Хилтону. Обдумайте простую программу:


x = 2
y = x + 1
z = x * 2


Для этого примера "продолжением x = 2 является y = x + 1; z = x * 2: Каждая отдельная строка кода имеет продолжение, полностью представляющее все предстоящее выполнение программы".

Продолжения имеют достаточно общий характер, поэтому могут эффективно моделировать нити. За годы существования нити, существующие в большинстве операционных систем, сильно потяжелели. Легенда представляет нити "легкими". Предполагается, что они гораздо проворнее, чем, например, процессы. Однако это уже давно не так. Практика промышленного применения заставили нити и процессы сойтись в своих требованиях к ресурсам. Нити неособенно легки.

Представьте на минутку идеальные нити - не те, которые предоставляют популярные ОС, а нити, как можно меньше нагруженные накладными расходами по взаимодействию и синхронизации. Это и есть микропоток, и продолжения могут моделировать микропотоки так же хорошо, как они моделируют любую другую параллельную структуру.

Это очень важно. Экспертам хорошо известно, что обычные многонитевые web-сервера, например, могут "забиться", запустив весьма скромное число нитей, обычно около пятидесяти. Микронити Stackless Python не только обладают всей простотой программирования, присущей языку Python, но и дают возможность даже весьма посредственному оборудованию обслуживать тысячи и десятки тысяч микронитей.

Наличие в Stackless Python микронитей - это не только вопрос надежности и производительности. Stackless Python делает микронити и соответствующие им структуры сохраняемыми, то есть они приобретают возможность сохранять и восстанавливать состояние. С точки зрения игр, это означает совершенно естественный и полный способ прерывания или сохранения любого объекта симуляции или даже перенос его в другой процесс или на другой хост. Игрок может предпочесть сохранить свою игру и вернуться к тому же самому моменту месяцы спустя. Пока этот механизм (известный в Python как "pickle") еще не существует в законченном виде, но уже стоит в планах Тисмера. Первые эксперименты обещают удачу, как только API станет более определенным.