Spec-Zone.ru › Django 6.0

Производительность и оптимизация

В этом документе представлен обзор методов и инструментов, которые помогут повысить эффективность работы кода Django: ускорить его выполнение и сократить потребление системных ресурсов.

Введение

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

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

Общие подходы

Для чего вы оптимизируете код?

Важно четко понимать, что именно вы подразумеваете под «производительностью». Она не измеряется только одним показателем.

Наиболее очевидная цель программы — повышение скорости, но иногда важны и другие улучшения производительности, например снижение потребления памяти или уменьшение нагрузки на базу данных или сеть.

Улучшения в одной области часто повышают производительность и в другой, но не всегда; иногда одно достигается за счет другого. Например, повышение скорости программы может привести к увеличению потребления памяти. Хуже того, это может оказаться контрпродуктивным: если для ускорения требуется столько памяти, что система начинает испытывать ее нехватку, результат будет скорее отрицательным.

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

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

Оценка производительности

Не стоит просто гадать или предполагать, где именно в коде возникают проблемы с производительностью.

Инструменты Django

django-debug-toolbar — очень удобный инструмент, который показывает, что делает ваш код и сколько времени на это уходит. В частности, он может показать все SQL-запросы, которые формирует ваша страница, и время выполнения каждого из них.

Для панели также доступны сторонние модули, которые могут, например, показывать эффективность кэширования и время рендеринга шаблонов.

Сторонние сервисы

Существует ряд бесплатных сервисов, которые анализируют производительность страниц вашего сайта и составляют отчеты с точки зрения удаленного HTTP-клиента, фактически имитируя взаимодействие реального пользователя с сайтом.

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

Есть также несколько платных сервисов, выполняющих аналогичный анализ. Некоторые из них учитывают особенности Django и могут интегрироваться с вашей кодовой базой, чтобы гораздо полнее оценивать ее производительность.

С самого начала делайте все правильно

Часть работы по оптимизации заключается в устранении проблем с производительностью, но некоторые улучшения можно заложить в код с самого начала, следуя рекомендациям, которых стоит придерживаться еще до того, как вы задумаетесь о повышении производительности.

В этом отношении Python — отличный язык: решения, которые выглядят элегантно и кажутся правильными, обычно оказываются и наиболее производительными. Как и любой другой навык, умение понимать, что «выглядит правильно», приходит с практикой, но одна из самых полезных рекомендаций такова:

Работайте на подходящем уровне

Django предлагает множество способов решения задач, но возможность сделать что-либо определенным способом еще не означает, что именно так и следует поступать. Например, одно и то же значение — скажем, количество элементов в коллекции — можно вычислить в QuerySet, на Python или в шаблоне.

Однако почти всегда быстрее выполнять эту работу на более низком, а не на более высоком уровне. На более высоких уровнях системе приходится работать с объектами через несколько уровней абстракции и слоев программных механизмов.

Иными словами, база данных обычно справляется с задачей быстрее, чем Python, а Python — быстрее, чем язык шаблонов:

# QuerySet operation on the database
# fast, because that's what databases are good at
my_bicycles.count()

# counting Python objects
# slower, because it requires a database query anyway, and processing
# of the Python objects
len(my_bicycles)
<!--
Django template filter
slower still, because it will have to count them in Python anyway,
and because of template language overheads
-->
{{ my_bicycles|length }}

Как правило, наиболее подходящий для задачи уровень — самый низкий из тех, на которых вам удобно писать код.

Примечание

Приведенный выше пример носит исключительно иллюстративный характер.

Во-первых, в реальной ситуации нужно учитывать, что происходит до и после подсчета, чтобы определить оптимальный способ выполнить его в данном конкретном контексте. В документе об оптимизации базы данных описан случай, когда подсчет в шаблоне предпочтительнее.

Во-вторых, можно рассмотреть и другие варианты: в реальной ситуации наиболее подходящим решением может оказаться {{ my_bicycles.count }}, который напрямую вызывает метод QuerySet count() из шаблона.

Кэширование

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

Это настолько важный и эффективный метод, что Django включает в себя полноценную систему кэширования, а также другие, более компактные средства кэширования.

Система кэширования

Система кэширования Django позволяет значительно повысить производительность, сохраняя динамическое содержимое, чтобы его не приходилось вычислять при каждом запросе.

Для удобства Django предлагает разные уровни детализации кэширования: можно кэшировать результаты отдельных представлений, только те фрагменты, которые сложно сформировать, или даже весь сайт целиком.

Кэширование не следует считать заменой улучшению плохо работающего кода, написанного неудачно. Это один из последних этапов создания хорошо работающего кода, а не короткий путь к результату.

cached_property

Часто метод экземпляра класса приходится вызывать несколько раз. Если функция выполняется долго, такие повторные вызовы могут быть неэффективны.

Декоратор cached_property сохраняет значение, возвращенное свойством; при следующем вызове функции для того же экземпляра будет возвращено сохраненное значение, а не выполнено повторное вычисление. Обратите внимание: это работает только с методами, у которых self — единственный аргумент, и превращает метод в свойство.

Некоторые компоненты Django также имеют собственные средства кэширования; они описаны ниже в разделах, посвященных соответствующим компонентам.

Понимание ленивых вычислений

Ленивые вычисления дополняют кэширование. Кэширование позволяет избежать повторных вычислений, сохраняя результаты; ленивые вычисления откладывают вычисление до тех пор, пока оно действительно не понадобится.

Ленивые вычисления позволяют ссылаться на объекты до их создания и даже до того, как их вообще можно будет создать. Это дает множество преимуществ.

Например, ленивый перевод можно использовать, даже если целевой язык еще неизвестен, поскольку перевод выполняется только тогда, когда строка действительно нужна, например при рендеринге шаблона.

Ленивые вычисления также позволяют сэкономить усилия, если изначально избегать выполнения ненужной работы. Иными словами, один из аспектов ленивых вычислений — ничего не делать, пока это не понадобится, поскольку в итоге задача может оказаться ненужной. Таким образом, ленивые вычисления влияют и на производительность: чем дороже обходится соответствующая работа, тем больше можно выиграть, отложив ее выполнение.

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

Ленивые вычисления в Django

Сам Django во многом использует ленивые вычисления. Хороший пример — вычисление QuerySet. Наборы запросов вычисляются лениво. Таким образом, можно создать QuerySet, передавать его и объединять с другими экземплярами QuerySet, не обращаясь при этом к базе данных за описанными в нем элементами. Передается объект QuerySet, а не коллекция элементов, которые в конечном итоге понадобятся из базы данных.

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

В Django также есть декоратор keep_lazy(). Он позволяет функции, вызванной с ленивым аргументом, самой работать лениво и выполнять вычисление только при необходимости. Таким образом, ленивый аргумент, вычисление которого может быть затратным, не будет вычисляться до тех пор, пока это действительно не потребуется.

Базы данных

Оптимизация базы данных

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

Другие советы по работе с базами данных

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

Это особенно полезно, например, на виртуализированных хостах с ограниченной пропускной способностью сети.

Производительность HTTP

Промежуточное ПО

В Django есть несколько полезных компонентов промежуточного ПО, которые помогают повысить производительность сайта. К ним относятся:

ConditionalGetMiddleware

Добавляет поддержку условных GET-запросов для современных браузеров на основе заголовков ETag и Last-Modified. При необходимости также вычисляет и устанавливает ETag.

GZipMiddleware

Сжимает ответы для всех современных браузеров, экономя пропускную способность сети и время передачи данных. Обратите внимание: GZipMiddleware в настоящее время считается угрозой безопасности и уязвим для атак, сводящих на нет защиту, обеспечиваемую TLS/SSL. Подробнее см. предупреждение в разделе GZipMiddleware.

Сеансы

Использование кэшированных сеансов

Использование кэшированных сеансов может повысить производительность, поскольку отпадает необходимость загружать данные сеанса из более медленного хранилища, например базы данных; вместо этого часто используемые данные сеанса хранятся в памяти.

Статические файлы

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

ManifestStaticFilesStorage

Используя возможности кэширования веб-браузеров, после первоначальной загрузки файла можно полностью исключить сетевые запросы для него.

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

«Минификация»

Некоторые сторонние инструменты и пакеты для Django позволяют «минифицировать» HTML, CSS и JavaScript. Они удаляют ненужные пробелы, символы новой строки и комментарии, а также сокращают имена переменных, уменьшая размер документов, публикуемых на сайте.

Производительность шаблонов

Обратите внимание:

  • использовать {% block %} быстрее, чем использовать {% include %}
  • шаблоны, составленные из множества небольших фрагментов, могут снизить производительность

Кэшированный загрузчик шаблонов

Включение cached template loader часто значительно повышает производительность, поскольку шаблоны не приходится компилировать при каждом рендеринге.

Использование разных версий доступного программного обеспечения

Иногда стоит проверить, доступны ли другие версии используемого вами программного обеспечения, которые работают лучше.

Эти методы предназначены для более опытных пользователей, которые хотят повысить производительность уже хорошо оптимизированного сайта на Django.

Однако это не волшебное решение проблем с производительностью, и вряд ли оно даст что-либо кроме незначительного выигрыша сайтам, на которых еще не реализованы базовые рекомендации.

Примечание

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

Новые версии обычно лучше, но не всегда

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

Это относится и к самому Django. Последующие выпуски включали ряд улучшений в разных частях системы, но все равно следует проверять производительность приложения в реальных условиях: в некоторых случаях изменения могут ухудшить ее, а не повысить.

Новые версии Python и его пакетов тоже часто работают лучше, но это нужно измерять, а не предполагать.

Примечание

Если вы не столкнулись с необычной проблемой производительности в конкретной версии, то, как правило, в новом выпуске найдете более широкие возможности, повышенную надежность и безопасность. Эти преимущества гораздо важнее любого возможного выигрыша или потери в производительности.

Альтернативы языку шаблонов Django

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

Jinja2 может повысить производительность, особенно скорость работы.

Разные альтернативные системы шаблонов в разной степени совместимы с языком шаблонов Django.

Примечание

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

Альтернативные реализации программного обеспечения

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

Однако большинство проблем с производительностью хорошо написанных сайтов на Django связано не с выполнением кода Python, а с неэффективными запросами к базе данных, кэшированием и шаблонами. Если вы полагаетесь на плохо написанный код Python, более быстрое его выполнение вряд ли решит проблемы с производительностью.

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

С учетом этих оговорок стоит обратить внимание на следующие варианты:

PyPy

PyPy — реализация Python на самом Python (стандартная реализация Python написана на C). PyPy может значительно повысить производительность, обычно в ресурсоемких приложениях.

Одна из ключевых целей проекта PyPy — совместимость с существующими API и библиотеками Python. Django совместим с версиями PyPy, соответствующими поддерживаемым версиям Python, но вам потребуется проверить совместимость других используемых библиотек.

Реализации библиотек Python на C

Некоторые библиотеки Python также реализованы на C и могут работать намного быстрее. Они предназначены для предоставления тех же API. Обратите внимание: проблемы совместимости и различия в поведении — не редкость, и не всегда их можно сразу заметить.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/6.0/topics/performance/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API