Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Единоборство с продуктивностью Tastypie API

Anna | 16.06.2014 | нет комментариев
Как я перетащил пакет Tastypie на Pony ORM и что из этого получилось.

Данная статья продолжает историю моей борьбы за эффективность приложений на python и django.

Короткое оглавление предыдущих серий:
— ORMы тормозят, причем дюже крепко — в 3-5 и больше раз
— А вот заляпочка для Django ORM
— Ух ты, вот данный ORM примерно не тормозит и кеширует все что только дозволено
— Вот так дозволено прикрутить высокопроизводительный Pony ORM к плану Django и применять его в ключевых местах

Вступление

Получив абсолютно удовлетворительные (по сопоставлению с Django ORM) итоги по скорости обращения к СУБД с поддержкой Pony ORM, я начал думать, как мне применять их на практике. Для начала, я сделалотображение модели данных Django на модель данных Pony. Сейчас, готовую модель данных дозволено применять в плане.

Там где код пишется с нуля, применять модель Pony взамен Django стало не легко, а дюже легко: признак `p` у всех моделей Django сейчас указывает на модель Pony. Впрочем — что же делать с теми готовыми пакетами, которые теснее применяют Django ORM?

К сожалению, результат один: переписывать либо дописывать, от того что синтаксис и семантика обращения к моделям и коллекциям у Pony ORM кардинально отличается от Django ORM — настоль, что замаскировать обращение к Pony ORM под обращение к Django ORM пока не представляется допустимым. Помимо того, я крепко подозреваю, что такая маскировка, будучи произведена, убьет все превосходства применения Pony ORM за счет потерь на промежуточном слое. Все-таки python — интерпретатор, и потери скажем на вызове функции крупны довольно, Дабы быть приметными даже на фоне обращения к СУБД. Именно такие потери, в числе прочих, видимо убивают продуктивность Django ORM и SQLAlchemy.

Мы планируем перевести каждый интерфейс (либо его огромную часть) нашего приложения на клиентскую сторону, применяя сервер как подрядчик данных через HTTP API. Таким образом, ключевым элементом становится API, которое мы реализуем с поддержкой пакета Tastypie, так что возрастание его продуктивности самым непосредственным образом должно отразиться на продуктивности интерфейса приложения и снижении всеобщей нагрузки на сайт.

И я взялся за Tastypie.

Как мне помогла конструкция Tastypie

Библиотека Tastypie, хоть и опирается на Django, имеет слой абстракции источников данных (Resource), само­стоятельный от Django ORM. Лишь дальнейший преемник, ModelResource, использует специфические для Django ORM обращения к данным. Таким образом, как я полагал сначала, мне необходимо было только унаследоваться от Resource и реализовать функционал, подобный ModelResource.

На практике, мне пришлось также сделать класс, параллельный ToManyField, от того что к моему разочарованию, в последнем оказалось несколько строк, ориентированных именно на Django ORM. Свой класс я обозвал SetField, от того что именно класс Set применяется в Pony ORM для обозначения отношения один-к-многим.

Что получилось

Получилось все легко восхитительно. В качестве примера, я применял модель данных из django.contrib.auth, заполнив ее приблизительно 1000 пользователей. Одному из пользователей я присвоил 159 прав на разные типы данных в системе (их — типов данных — у нас много накопилось) и запрашивал этого пользователя совместно с его правами через API, применяя данный вызов в качестве примера.

Вот как выглядело определение источника данных для ветхого API v2, использовавшего Django ORM (обратите внимание, что аутентификация и авторизация исключены — для правильного измерения продуктивности).

class PermissionResource(ModelResource):
    class Meta:
        queryset = auth_models.Permission.objects.all()
        object_model = queryset.model
        filtering = dict([(n,ALL_WITH_RELATIONS) for n in object_model._meta.get_all_field_names()])
        resource_name = 'auth/permission'

class UserResource(ModelResource):
    user_permissions = ToManyField(PermissionResource,'user_permissions',related_name='user_set',null=True)
    class Meta:
        queryset = auth_models.User.objects.all()
        object_model = queryset.model
        filtering = dict([(n,ALL_WITH_RELATIONS) for n in object_model._meta.get_all_field_names()])
        resource_name = 'auth/user'

Ну а вот так выглядит определение для нового API v3, ориентированного на применение Pony ORM коллективно с пакетом Djony:

class PermissionResource(DjonyResource):
    class Meta:
        object_model = auth_models.Permission
        filtering = dict([(n,ALL_WITH_RELATIONS) for n in object_model._meta.get_all_field_names()])
        resource_name = 'auth/permission'

class UserResource(DjonyResource):
    user_permissions = SetField(PermissionResource,'user_permissions',related_name='user_set',null=True)
    class Meta:
        object_model = auth_models.User
        filtering = dict([(n,ALL_WITH_RELATIONS) for n in object_model._meta.get_all_field_names()])
        resource_name = 'auth/user'

Обратите внимание, что в определении метаданных применяется модель Django а не Pony. Это связано с тем, что модель Pony не содержит многих признаков, характерных для Django ORM, но не надобных для определения собственно конструкции данных, таких как скажем help_text. Вопрос о размещении таких метаданных на самом деле значим, но возможно, его обсуждение выходит за рамки данной статьи.

Сервер был развернут на моем скромном рабочем компьютере, имеющим 2 ядра на 2.2 ГГц и 3 Гб оперативной памяти. Тестовый заказчик запускался с того же компьютера. В качестве последнего, запускался пакет ab (Apache Benchmark):

seva@SEVA (2):~/djony$ ab -n 100 -c 4 "http://localhost:8080/api/v2/auth/user/3/?format=json"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done

Server Software:        nginx/1.1.19
Server Hostname:        localhost
Server Port:            8080

Document Path:          /api/v2/auth/user/3/?format=json
Document Length:        5467 bytes

Concurrency Level:      4
Time taken for tests:   17.331 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      582900 bytes
HTML transferred:       546700 bytes
Requests per second:    5.77 [#/sec] (mean)
Time per request:       693.256 [ms] (mean)
Time per request:       173.314 [ms] (mean, across all concurrent requests)
Transfer rate:          32.84 [Kbytes/sec] received

Connection Times (ms)
              min  mean[ /-sd] median   max
Connect:        0    0   1.5      0       9
Processing:   313  685 486.1    575    3357
Waiting:      312  684 485.8    574    3355
Total:        313  685 486.7    575    3357

Percentage of the requests served within a certain time (ms)
  50%    575
  66%    618
  75%    647
  80%    670
  90%    819
  95%   1320
  98%   2797
  99%   3357
 100%   3357 (longest request)
seva@SEVA (2):~/djony$ ab -n 100 -c 4 "http://localhost:8080/api/v3/auth/user/3/?format=json"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done

Server Software:        nginx/1.1.19
Server Hostname:        localhost
Server Port:            8080

Document Path:          /api/v3/auth/user/3/?format=json
Document Length:        5467 bytes

Concurrency Level:      4
Time taken for tests:   8.339 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      582900 bytes
HTML transferred:       546700 bytes
Requests per second:    11.99 [#/sec] (mean)
Time per request:       333.557 [ms] (mean)
Time per request:       83.389 [ms] (mean, across all concurrent requests)
Transfer rate:          68.26 [Kbytes/sec] received

Connection Times (ms)
              min  mean[ /-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   137  317 375.9    243    2753
Waiting:      137  316 375.7    243    2751
Total:        137  317 375.9    243    2753

Percentage of the requests served within a certain time (ms)
  50%    243
  66%    264
  75%    282
  80%    299
  90%    351
  95%    433
  98%   2670
  99%   2753
 100%   2753 (longest request)

Как видите, использование Pony ORM дало тут возрастание продуктивности API в 2 раза.

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

seva@SEVA (2):~/djony$ ab -n 20 -c 4 "http://localhost:8080/api/v2/auth/user/?format=json&limit=0"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done

Server Software:        nginx/1.1.19
Server Hostname:        localhost
Server Port:            8080

Document Path:          /api/v2/auth/user/?format=json&limit=0
Document Length:        306326 bytes

Concurrency Level:      4
Time taken for tests:   40.891 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Total transferred:      6133760 bytes
HTML transferred:       6126520 bytes
Requests per second:    0.49 [#/sec] (mean)
Time per request:       8178.157 [ms] (mean)
Time per request:       2044.539 [ms] (mean, across all concurrent requests)
Transfer rate:          146.49 [Kbytes/sec] received

Connection Times (ms)
              min  mean[ /-sd] median   max
Connect:        0    0   0.1      0       0
Processing:  6235 7976 1035.4   7980   10671
Waiting:     6225 7959 1033.0   7958   10654
Total:       6235 7976 1035.4   7980   10671

Percentage of the requests served within a certain time (ms)
  50%   7980
  66%   8177
  75%   8287
  80%   8390
  90%  10001
  95%  10671
  98%  10671
  99%  10671
 100%  10671 (longest request)
seva@SEVA (2):~/djony$ ab -n 20 -c 4 "http://localhost:8080/api/v3/auth/user/?format=json&limit=0"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done

Server Software:        nginx/1.1.19
Server Hostname:        localhost
Server Port:            8080

Document Path:          /api/v3/auth/user/?format=json&limit=0
Document Length:        306326 bytes

Concurrency Level:      4
Time taken for tests:   11.841 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Total transferred:      6133760 bytes
HTML transferred:       6126520 bytes
Requests per second:    1.69 [#/sec] (mean)
Time per request:       2368.136 [ms] (mean)
Time per request:       592.034 [ms] (mean, across all concurrent requests)
Transfer rate:          505.88 [Kbytes/sec] received

Connection Times (ms)
              min  mean[ /-sd] median   max
Connect:        0    0   0.1      0       0
Processing:  1024 2269 806.2   2227    4492
Waiting:     1017 2252 803.6   2211    4472
Total:       1024 2269 806.2   2227    4492

Percentage of the requests served within a certain time (ms)
  50%   2227
  66%   2336
  75%   2395
  80%   2406
  90%   4140
  95%   4492
  98%   4492
  99%   4492
 100%   4492 (longest request)

Продуктивность API повысилась больше чем в 4 раза!

Что еще предстоит

Пока не реализованы авторизация и аутентификация, однако я не вижу специальных задач при их реализации.

Есть задача с реализацией фильтров по критериям вида regex, week_day и search, от того что в Pony ORM схожие критерии пока отсутствуют.

Завершение

Внедрение Pony ORM в качестве замены Django ORM в готовые пакеты-приложения Django является абсолютно допустимым и дюже пригодным в плане возрастания продуктивности занятием. Делу крепко помогает отличная абстракция классов внутри пакета, в частности — присутствие слоя, не зависящего от Django ORM.

Я приглашаю всех, кто заинтересован в возрастании продуктивности своих приложений Django, присоединяться к открытым планам djony (скрещивание Pony и Django) и tastypie_djony (убыстрение Tastypie с поддержкой Pony ORM) для их быстрейшего доведения до устойчивого индустриального примера.

План Pony ORM является планом с открытым начальным кодом.

Обычно напоминаю, что разработчики Pony ORM являются пока еще readonly-пользователями Програпрогра:

AlexeyMalashkevich m.alexey@gmail.com

metaprogrammer alexander.kozlovsky@gmail.com

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB