Spec-Zone.ru › Django 4.1

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

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

Введение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Yahoo’s Yslow
  • 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. Наборы запросов ленивые. Таким образом, набор запросов можно создать, передать и объединить с другими QuerySets, не выполняя фактических обращений к базе данных для получения описанных элементов. Передаётся объект 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/4.1/topics/performance/

Spec-Zone.ru

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