Django - 使用templatetags渲染许多模板非常慢

时间:2012-02-07 19:39:32

标签: django optimization django-templates

说,我有一个带照片库的页面。每个缩略图例如照片,国家,作者等。我使用模板标签(加载指定的模板)渲染这些项目/小部件 - 由于DRY(我在页面的不同位置分别使用这些项目/小部件),它就是这样。

这很慢。

我使用django-debug-toolbar执行了一些分析:

SQL Queries: default 84.81 ms (147 queries)

可是:

Total CPU time: 5768.360 msec

等待太久了。

经过一番分析后发现,主要罪魁祸首是模板化。

当我想要显示例如通过模板呈现150张照片,600个相关项目/小部件。这意味着600次I / O操作甚至更多。将这些小部件移动到主模板可以解决问题,但不能保持DRY。

所以我的问题是如何避免这种行为?干,慢,干,快? 我宁愿干得快......

6 个答案:

答案 0 :(得分:11)

经过几个小时的分析和搜索......

感谢您的帮助,但在这种情况下,我认为到目前为止最好的解决方案是使用Template fragment caching

我尝试了它并获得了70-80%的速度性能!

{% load cache %}
{% cache 3600 mywidget_id %}
    .. rendered mywidget is cached ..
{% endcache %}

答案 1 :(得分:10)

您可能想要尝试caching template loaderdjango.template.loaders.cached.Loader - 它肯定会减少所需的IO数量。

编辑添加您需要小心,假设只是因为大部分时间花在模板渲染阶段,查询计数不应该受到责备。不要忘记查询集是惰性的,除非您在视图中专门切片或迭代它们,否则只会在加载模板时对它们进行求值。我会说通过充分利用select_related和其他技术来减少查询次数应该是非常有帮助的。

答案 2 :(得分:4)

我假设你正在使用调试工具栏,你正在开发这些数字。但是,因此,这些不是“真实的”数字。

内置的Django服务器非常适合开发,但它有许多缺点,使得 比实际的Web服务器慢。首先,它是单线程的,因此这意味着没有并行请求。这也意味着IO操作是离散的。其次,它不仅要为Django提供请求,还要为静态资源提供服务。

多长时间,如果您想真正分析网站的页面加载时间,您需要在本地安装一个真正的网络服务器。基本上就像在生产环境中那样设置它。我愿意下注请求时间然后。

答案 3 :(得分:0)

这可能不适用于此特定问题,但在某些情况下,它帮助我在查询中使用select_related。可能不是这种情况,但可能会降低您的查询次数。

答案 4 :(得分:0)

花在查询上的时间相对较少。 但ORM需要更多时间来生成这些查询并将结果解析为模型实例。

因此,尽管查询数量很大,但由于ORM较慢,您的应用程序受CPU限制(在您的情况下可能需要一秒钟)。所以你必须减少查询次数。

很可能查询是在模板标记内完成的。因此,您必须在几个查询中获取所需数据,并将其设置在照片实例上。

{% 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属性中获得此信息。你在一个查询中实现了这一点。

答案 5 :(得分:0)

我有同样的问题,也许出于同样的原因。我优化了自定义模板标记的性能。 db请求数从640减少到2,结果db时间不到20ms。然而,我的页面变慢了! 7s - > 10秒。叹。我尝试了一个缓存的模板加载器,没有效果。

我放弃了,禁用了django调试工具栏,之后响应时间降到了1.2秒,令人难以置信!就我而言,巨大的响应时间只是由调试工具栏引起的!可以找到相关问题here。我没有深入研究这个工具栏问题,因为我打算使用模板片段缓存来缓存模板标签。在开发过程中,我每15分钟有10秒的响应时间,我可以忍受。无论如何,希望这会有所帮助。