Spec-Zone.ru › Django 4.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, передать его и объединить с другими QuerySets, не выполняя фактических обращений к базе данных для извлечения элементов, которые они описывают. Передаётся объект 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 совместим, но вам нужно проверить совместимость других используемых вами библиотек.

C-реализации библиотек Python

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

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

Spec-Zone.ru

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