Spec-Zone.ru › Django 1.8

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

В данном документе представлен обзор техник и инструментов, которые помогут сделать ваш код 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 может быть создан, передан и объединён с другими 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.8/topics/performance/

Spec-Zone.ru

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