Spec-Zone.ru › Django 5.0

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

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

Введение

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

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

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

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

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

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

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

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

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

Измерение производительности

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

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

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

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

Сервисы сторонних разработчиков

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

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

  • Yslow от Yahoo
  • Google PageSpeed

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

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

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

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

Работайте на соответствующем уровне

Django предлагает множество различных способов подхода к задачам, но то, что что-то можно сделать определённым образом, не означает, что это самый подходящий способ. Например, вы можете обнаружить, что можете вычислить одно и то же — количество элементов в коллекции, возможно — в QuerySet, в 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 довольно ленивый. Хороший пример этого можно найти в вычислении QuerySets. QuerySet — ленивый. Таким образом, QuerySet можно создать, передать и объединить с другими QuerySets, не совершая фактических обращений к базе данных для получения описываемых им элементов. То, что передаётся — это объект QuerySet, а не набор элементов, которые — в конечном итоге — будут запрошены из базы данных.

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

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

Базы данных

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

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

Другие советы, связанные с базой данных

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

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

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

Средства промежуточного слоя

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

ConditionalGetMiddleware

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

GZipMiddleware

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

Сессии

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

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

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

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

ManifestStaticFilesStorage

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

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

“Минификация”

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

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

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

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

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

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

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

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

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

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

Примечание

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

Новее - часто, но не всегда - лучше

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

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

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

Примечание

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

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

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

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

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

Примечание

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

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

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

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

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

С учетом этих оговорок вы должны знать о:

PyPy

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

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

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

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

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

Spec-Zone.ru

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