说,我有一个带照片库的页面。每个缩略图例如照片,国家,作者等。我使用模板标签(加载指定的模板)渲染这些项目/小部件 - 由于DRY(我在页面的不同位置分别使用这些项目/小部件),它就是这样。
这很慢。
我使用django-debug-toolbar执行了一些分析:
SQL Queries: default 84.81 ms (147 queries)
可是:
Total CPU time: 5768.360 msec
等待太久了。
经过一番分析后发现,主要罪魁祸首是模板化。
当我想要显示例如通过模板呈现150张照片,600个相关项目/小部件。这意味着600次I / O操作甚至更多。将这些小部件移动到主模板可以解决问题,但不能保持DRY。
所以我的问题是如何避免这种行为?干,慢,干,快? 我宁愿干得快......
答案 0 :(得分:11)
经过几个小时的分析和搜索......
感谢您的帮助,但在这种情况下,我认为到目前为止最好的解决方案是使用Template fragment caching:
我尝试了它并获得了70-80%的速度性能!
{% load cache %}
{% cache 3600 mywidget_id %}
.. rendered mywidget is cached ..
{% endcache %}
答案 1 :(得分:10)
您可能想要尝试caching template loader,django.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秒的响应时间,我可以忍受。无论如何,希望这会有所帮助。