Spec-Zone.ru › Django 1.9

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

В данном документе рассматриваются методы и инструменты, которые помогут вам добиться большей эффективности кода 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 ленивые. Таким образом, QuerySet можно создать, передавать и комбинировать с другими QuerySets, не вызывая фактических обращений к базе данных для получения элементов, которые они описывают. Передаваемым объектом является QuerySet объект, а не коллекция элементов, которые – в конечном итоге – потребуются из базы данных.

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

Django также предлагает декоратор allow_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.9/topics/performance/

Spec-Zone.ru

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