Spec-Zone.ru › Django 3.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. Наборы запросов — ленивые. Таким образом, набор запросов можно создать, передать и комбинировать с другими 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/3.0/topics/performance/

Spec-Zone.ru

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