Spec-Zone.ru › Django 1.10

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

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

Введение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Yslow от Yahoo
  • Google PageSpeed

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

Решайте задачи правильно с самого начала

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

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

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

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

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

То есть база данных, как правило, может выполнять операции быстрее, чем 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, а не коллекция элементов, которые — в конечном счёте — будут необходимы из базы данных.

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

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

Базы данных

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

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

Дополнительные советы по базам данных

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

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

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

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

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

ConditionalGetMiddleware

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

GZipMiddleware

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

Сессии

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

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

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

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

CachedStaticFilesStorage

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

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

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

Несколько сторонних инструментов и пакетов 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/1.10/topics/performance/

Spec-Zone.ru

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