Поиск узких мест производительности проекта на Django
Вступление
При оптимизации производительности веб-приложения распространенная ошибка — начинать с оптимизации самой медленной страницы (или API). Помимо учета времени отклика, мы также должны учитывать трафик, который он получает, чтобы определить порядок оптимизации.
В этой статье мы расскажем о веб-приложении Django, найдем узкие места с высокой эффективностью, а затем приступим к их оптимизации для повышения производительности. Посмотрите также совет, как узнать, какие SQL запросы выполняет ваш проект на Django и сколько они занимают времени.
Профилирование
django-silk
— это инструмент для профилирования с открытым исходным кодом, который перехватывает и сохраняет данные HTTP-запросов. Установим его с помощью pip:
pip install django-silk
Добавим silk в установленные пакеты и в миддлвар в настройках проекта:
MIDDLEWARE = [
...
'silk.middleware.SilkyMiddleware',
...
]
INSTALLED_APPS = (
...
'silk'
)
Запустите миграцию, чтобы Silk мог создавать необходимые таблицы базы данных для хранения данных профилирования:
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py collectstatic
На странице запросов silk (http://host/silk/requests/) мы можем видеть все запросы и сортировать их по общему времени или времени, потраченному на базу данных.
Узкие места (Bottlenecks)
Silk создает таблицу silk_request, которая содержит информацию о запросах, обработанных Django.
$ pgcli
library> \d silk_request;
+--------------------+--------------------------+-------------+
| Column | Type | Modifiers |
|--------------------+--------------------------+-------------|
| id | character varying(36) | not null |
| path | character varying(190) | not null |
| time_taken | double precision | not null |
...
Мы можем сгруппировать данные этих запросов по пути, рассчитать количество запросов, среднее время выполнения и коэффициент влияния каждого пути. Поскольку мы учитываем время отклика и трафик, фактор влияния будет являться произведением среднего времени отклика и количества запросов по этому пути.
library> SELECT
s.*, round((s.avg_time * s.count)/max(s.avg_time*s.count) over ()::NUMERIC,2) as impact
FROM
(select path, round(avg(time_taken)::numeric,2) as avg_time, count(path) as count from silk_request group by PATH)
s
ORDER BY impact DESC;
+-------------------------+------------+---------+----------+
| path | avg_time | count | impact |
|-------------------------+------------+---------+----------|
| /point/book/book/ | 239.90 | 1400 | 1.00 |
| /point/book/data/ | 94.81 | 1900 | 0.54 |
| /point/ | 152.49 | 900 | 0.41 |
| /point/login/ | 307.03 | 400 | 0.37 |
| / | 106.51 | 1000 | 0.32 |
| /point/auth/user/ | 494.11 | 200 | 0.29 |
...
Мы видим, что /point/book/book/
оказывает наибольшее влияние, хотя это не самая посещаемая ссылка и не самое медленное отображение (view). Оптимизация этого представления в первую очередь приводит к повышению общей производительности веб-приложения.
Заключение
В этой статье мы узнали, как легко начать профилирование веб-приложения Django и выявлять узкие места для повышения производительности. В следующей статье мы узнаем, как оптимизировать эти узкие места, подробно рассмотрев их.
Вернуться на верх