Django - рендеринг многих шаблонов с использованием шаблонов очень медленный - PullRequest
15 голосов
/ 07 февраля 2012

Скажите, у меня есть страница с фотогалереей.Каждый эскиз имеет, например, фотографию, страну, автора и так далее.Я визуализирую эти элементы / виджеты, используя теги шаблонов (которые загружают указанные шаблоны) - так происходит из-за СУХОГО (я использую эти элементы / виджеты отдельно в разных местах на странице).

И это очень медленно.

Я выполнил некоторое профилирование, используя django-debug-toolbar:

SQL Queries: default 84.81 ms (147 queries)

Но:

Total CPU time: 5768.360 msec

Что слишком долго ждать.

После некоторого анализа выяснилось, что основным виновником является шаблонинг enginge.

Когда я хочу отобразить, например, 150 фотографий, 600 связанных элементов / виджетов визуализируются с помощью шаблонов.Это означает 600 операций ввода-вывода или даже больше.Перемещение этих виджетов в основной шаблон решает проблему, но не сохраняет СУХОЙ.

Итак, мой вопрос, как можно избежать такого поведения?Быть СУХИМ и медленным или не СУХИМ и быстрым?Я бы предпочел быть СУХИМ и быстрым ...

Ответы [ 6 ]

11 голосов
/ 09 февраля 2012

После нескольких часов профилирования и поиска ...

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

Я попробовал и набрал 70-80% скорости!

{% load cache %}
{% cache 3600 mywidget_id %}
    .. rendered mywidget is cached ..
{% endcache %}
10 голосов
/ 07 февраля 2012

Возможно, вы захотите попробовать загрузчик шаблонов кэширования , django.template.loaders.cached.Loader - это, безусловно, должно уменьшить количество необходимых операций ввода-вывода.

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

4 голосов
/ 08 февраля 2012

Я предполагаю, что поскольку вы используете панель инструментов отладки, вы получаете эти цифры в процессе разработки.Однако из-за этого это не «реальные» числа.

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

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

0 голосов
/ 15 декабря 2015

У меня была та же проблема, и, возможно, по той же причине. Я оптимизировал производительность пользовательского тега шаблона. Количество запросов к базе данных упало с 640 до 2, и в результате время обработки базы данных было менее 20 мс Моя страница, однако, стала медленнее! 7 с -> 10 с. Вздох. Я пробовал загрузчик кэшированных шаблонов, без эффекта.

Я сдался, отключил панель отладки django, после чего время отклика упало до 1.2s, невероятно !! В моем случае огромное время отклика было вызвано только панелью отладки! Связанную проблему можно найти здесь . Я не буду углубляться в эту проблему панели инструментов, так как я планировал кэшировать тег шаблона с помощью кэширования фрагментов шаблона в любом случае. Во время разработки у меня есть время отклика 10 с каждые 15 минут, с которым я могу жить. В любом случае, надеюсь, это поможет.

0 голосов
/ 01 мая 2012

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

Итак, несмотря на огромное количество запросов, ваше приложение связано с процессором из-за медленной ORM (в вашем случае это может занять секунду). Так что вам все равно придется сократить количество запросов.

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

{% for photo in photos|annotate_comment_count %}
   ...
{% endfor %}

def annotate_comment_count(photo_list):
    counts = dict(Comment.objects.filter(photo__in=photo_list).values('photo') \
                                 .annotate(count=models.Count('id')))
    for photo in photo_list:
        photo.comments_count = counts[photo.pk]
    return photo_list

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

0 голосов
/ 08 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...