Spec-Zone.ru › Django 2.2

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

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

Введение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Yslow от Yahoo
  • PageSpeed от Google

Также есть несколько платных сервисов, которые выполняют аналогичный анализ, включая некоторые, которые ориентированы на 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. QuerySets ленивы. Таким образом, 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/2.2/topics/performance/

Spec-Zone.ru

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