Сегодня узнал о выпуске PyPy 1.2 и конечно сразу решил попробовать, что это такое :) Все эксперименты ниже проводил на MacBook Pro (Mac OS X Snow Leopard) с процессором 2.26Гц Intel Core 2 Duo и 2Гб памяти. Тесты производительности заявляли об ускорении работы Джанго в 2.86 раз. Проверим :)
Скачал и поставил себе готовую версию под Mac OS X c JIT компилятором. Узнал, где у PyPy лежат сторонние библиотеки командой:
pypy -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
и создал по этому пути simlink на директорию с библиотеками Python 2.6.4, чтобы не ставить все библиотеки заново под PyPy:
sudo ln -s /path/to/pypy/site-package/folder /path/to/python/site-package/folder
Для начала запустил pypy и импортировал Джанго: import django. Ошибок не возникло. Уже хорошо! Несколько других библиотек тоже импортировалось без ошибок: jinja2, html5lib, debug_toolbar, memcache и т.д. Следующим шагом, попробовал запустить свой блог под PyPy из папки проекта блога:
pypy manage.py runserver
Чудо не произошло, как и заявлено на сайте, PyPy не поддерживает CPython C API. Соответственно не работают библиотеки для работы с базами данных Postgersql и Mysql. Сервер не стартовал. Это пожалуй самое не достающее на данный момент в PyPy для его тестирования на реальных проектах. Второй недостаток: на данный момент поддерживается версия Питона 2.5.2
Ну ладно, попробуем все же сравнить скорость работы по сравнению с Python 2.6.4 без использования баз данных. Для этого я создал простой view (сразу с кодом замера скорости работы):
from datetime import datetime
import time
from django.shortcuts import render_to_response
from django.template import RequestContext
def test(request):
start = time.time()
tag = {'title': 'поиск по тэгу ...'}
entries = [{'id': 1, 'status': 1, 'date': datetime.now(), 'title': 'Пост 1',
'description': 'Мой первый пост в этом блоге'}]
for i in xrange(1000):
render_to_response('pypy/test.html',
{'entries': entries, 'tag': tag},
RequestContext(request))
end = time.time()
print 'Time: %s' % (end - start)
return render_to_response('pypy/test.html',
{'entries': entries, 'tag': tag},
RequestContext(request))
Файл темплэйта pypy/test.html тоже достаточно простой, но тем не менее там используются тэги if, for и несколько фильтров: capfirst, date. Попробовал открыть страницу, генерируемую данным view. Упало, с показом стандартной страницы ошибки джанго. Эта же страница нормально открылась под Python 2.6.4. Поразбиравшись в чем проблема обнаружил, что дело всего ли в одной строке кода в коде поиска загрузчика темплэйтов в Джанго:
if hasattr(loader, '__iter__'):
После комментирования этого кода в Джанго (по иронии судьбы это как раз новый код кэширования загрузки темплэйтов, появившийся в Джанго 1.2) страница нормально открылась. Завел баг в баг-трекере проекта PyPy и буквально через несколько минут баг закрыли, так как это оказался дубликат уже заведенного бага #354. В следующей версии будет поправлено. Оперативно, что радует.
Время открытия страницы получилось интересным (привожу среднее значение):
PyPy 1.2:
7.5 секунды
Python 2.6.4:
4.65 секунды
Возможно это из-за того что, Python 2.6.4 работает в 64-битном режиме, а PyPy в режиме эмуляции 32-битного режиме, но скорость получилась почти в два раза медленнее. Наблюдение за потребляемой PyPy памятью показало, что при запуске джанго-сервера под PyPy сразу после запуска съедается около 38 Мб, после многокрастного открытия тестовой страницы в браузере расход памяти возрастает до 70 Мб. Что тоже в несколько раз больше, чем у Python 2.6.4.
Для реального использования пока не подходит, но тем не менее ребята просто герои, что делают этот проект на полном энтузиазме в свое свободное время. Обязательно пожертвую проекту 5-10 евро, как разберусь со своим аккаунтом в PayPal (кнопка Donate есть на центральной странице проекта справа). Считаю, что нужно поддерживать такие проекты, если хотим в будущем увидеть развитие языка Python.
Покопавшись, нашел решение для подключение библиотек, использующих CPython C API, в частности для библиотек работы с базами данных. Решение описано в блоге PyPy. Делаем все по инструкции, кроме накатывания патча, это нужно только для PyQt. Запускаем rpyc сервер в отдельном окне:
python rpyc/servers/classic_server.py
Потом для каждой библиотеки, которая у нас не запускается в папке /path/to/PyPy/pypy/lib/ создаем питоновский файл, который называется, как библиотека. Например, для библиотеки работы с Mysql: MySQLdb.py. В файл добавляем всегда одно и тоже содержимое:
from _rpyc_support import proxy_module
proxy_module(globals())
del proxy_module
После этого импорт данной библиотеки начинает работать, правда скорее работать это будет очень медленно.
Дополнение: Мой патч включили в Джанго 1.2 и теперь джанговские темплэйты работают с PyPy 1.2!
| homa - 14.03.2010 |
|
| kostia.lopuhin - 14.03.2010 |
Интересно! А вы не пробовали использовать sqlite3? как я понимаю, pypy должен ее поддерживать http://pypy.org/compat.html - (written in pure python). Только вот у меня что-то не получилось... Из того, что тестировал сам, вынес что pypy свертки обрабатывает раза в 2 медленнее, чем аналогичные циклы. |
| Толик Востряков - 14.03.2010 |
Нет, не пробовал, так как не применяю его в своих проектах, но получиться должно, так как в состав PyPy 1.2 входит своя версия sqlite3. Во-вторых, в конце поста в разделе "Дополнение" описано как подключить библиотеки, которые сразу не заработали с PyPy, правда это медленный вариант, только для экспериментов. |
| kostia.lopuhin - 14.03.2010 |
О, получилось наконец заставить работать с sqlite, в моем случае нужно было немного поправить код загрузки библиотеки в pypy/lib/sqlite3/dbapi2.py. Но пока оказывается, что оно раза в 2-3 медленнее, эх... может надо как-то по-другому мерить) |