- PVSM.RU - https://www.pvsm.ru -
Предыдущий пост [1] посвященный производительности, описывал Pony ORM [2], показавший фантастические результаты по сравнению с Django ORM и SQLAlchemy.
Впечатленный столь неординарными результатами и озабоченный производительностью собственного проекта, я решил внедрить Pony ORM в свой проект. Что из этого получилось, см подкатом.
Конечно, можно было бы переписать проект заново. Этот соблазн всегда витает над разработчиком, встретившим проблемы, корни которых лежат в используемом инструменте. Однако, объем уже написанного кода, огромная разветвленная модель данных, да и впечатляющее количество использованных в проекте вполне рабочих плагинов-приложений для Django ставят на этом пути большой и жирный крест.
Некоторое время назад, в поисках альтернативы Django ORM, я наткнулся на интересный проект Aldjemy [3]. Это небольшая навеска над Django ORM, позволяющая использовать структуру моделей Django для построения альтернативной иерархии моделей SQLAlchemy. Такой подход дает возможность, сохраняя основу проекта (в том числе — всю модель данных Django), использовать SQLAlchemy именно и только там, где вы захотите. Вдохновленный идеей этого проекта и слизав некоторое количество строк кода, я сделал аналогичную библиотеку [4] для прикрутки Pony ORM к Django ORM, назвав ее djony (DJango pONY).
Использование djony более чем просто. После установки djony в систему (например с помощью команды pip install git+git://github.com/nnseva/djony.git@master#egg=djony), мы можем указать djony в качестве одного из используемых приложений в settings.py. Нужно только помнить, что djony обязательно должен быть самым последним приложением в списке.
Теперь у каждой из моделей Django (именно моделей — как классов) появился атрибут `p` (от слова pony). Это и есть модель Pony ORM. Ее можно использовать везде, где согласно документации [5] Pony, нужно использовать модель. Вам понадобится также модуль orm, его можно импортировать из модуля pony (from pony import orm). Альтернативно, вы можете использовать модуль djony.orm, содержащий все переменные модуля pony.orm, а также специфические для djony функции и переменные.
Объекты моделей Pony ORM будут содержать только поля данных и коллекции объектов согласно модели данных и структуре отношений (возможно, в будущем надо будет прикрутить возможность добавления своих членов в автоматически создаваемые модели Pony ORM).
Попробуем теперь потестировать на производительность одну из самых популярных операций — проверку прав пользователя.
Для Django мы будем использовать готовую функцию User.has_perm. Разумеется, для Pony ORM нужно будет написать код, примерно эквивалентный этой функции::
def has_perm(user,perm):
if not user.is_active:
return False
app_label,codename = perm.split('.')
for p in orm.select(
p for p in Permission.p
if
(user in p.user_set or user in p.group_set.user_set) and
p.codename == codename and
p.content_type.app_label == app_label
):
return True
return False
Посмотрим на результаты тестирования (для тестирования, в базе было заведено 1000 пользователей, выполняющих для теста роль балласта).
>>> import test_pony
>>> import test_django
>>> test_django.test_django()
check user permissions: django req/seq: 170.308759221 req time (ms): 5.8716886
>>> test_pony.test_pony()
check user permissions: pony req/seq: 729.517146462 req time (ms): 1.3707697
Как видим, мы получили прирост более чем в 4 раза. Очень неплохо!
import datetime
from django.contrib.auth.models import User
def test_django():
t1 = datetime.datetime.now()
for i in range(10000):
test()
t2 = datetime.datetime.now()
print "check user permissions: django req/seq:",10000/(t2-t1).total_seconds(),'req time (ms):',(t2-t1).total_seconds()/10.
def test():
user = User.objects.get(username='testuser')
return user.has_perm('auth.add_user')
import datetime
from django.contrib.auth.models import User, Permission
def test_pony():
t1 = datetime.datetime.now()
for i in range(10000):
test()
t2 = datetime.datetime.now()
print "check user permissions: pony req/seq:",10000/(t2-t1).total_seconds(),'req time (ms):',(t2-t1).total_seconds()/10.
from djony import orm
@orm.db_session
def test():
user = User.p.get(username='testuser')
return has_perm(user,'auth.add_user')
def has_perm(user,perm):
if not user.is_active:
return False
app_label,codename = perm.split('.')
for p in orm.select(
p for p in Permission.p
if
(user in p.user_set or user in p.group_set.user_set) and
p.codename == codename and
p.content_type.app_label == app_label
):
return True
return False
Автор: nnseva
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/45924
Ссылки в тексте:
[1] пост: http://habrahabr.ru/post/188842/
[2] Pony ORM: http://www.ponyorm.com/
[3] Aldjemy: https://github.com/Deepwalker/aldjemy
[4] аналогичную библиотеку: https://github.com/nnseva/djony
[5] согласно документации: http://doc.ponyorm.com/
[6] Источник: http://habrahabr.ru/post/197962/
Нажмите здесь для печати.