django很慢

时间:2010-11-06 15:33:16

标签: python django django-templates

一些分析显示模板渲染是罪魁祸首。 (我正在尝试一个只有缓存查询的页面。) 但是,模板很简单。 最复杂的部分是一个运行10次的嵌套循环,但是如果一切顺利,嵌套循环就不会运行,因为它被缓存了。 (就像在我的测试中一样)

{% for p in posts %}
 --{{p.by.username}}
 --{{p.text}}
 {% cache 600 p p.timestamp %}
    {% for img in p.images.all %}
      --{{img.path}}
    {% endfor %}
 {% endcache %}
{% endfor %}

我在dev上获得了~80 req / s。此页面的服务器。 (我发现我可以在生产部署中将该数字乘以3) 为了进行比较,对于只包含一个短静态字符串的普通模板,我得到1000req / s。

这是一个已知问题吗?我该如何纠正/避免它?

2 个答案:

答案 0 :(得分:2)

(显然我不是“karmic”足以发表评论,或者我会将其作为评论而不是答案发布)

您能详细说明“仅缓存查询”的含义吗?

除此之外,在我看来,您的问题可能是您在模板渲染过程中经常访问数据库

{% for p in posts %}
 --{{p.by.username}} {# 1 #}
 --{{p.text}}
 {% cache 600 p p.timestamp %}
    {% for img in p.images.all %} {# 2 #}
      --{{img.path}}
    {% endfor %}
 {% endcache %}
{% endfor %}

您为模板提供“帖子”;这是一个查询,你说过它有100个结果。

对于帖子的每次迭代,然后,你在{# 1 #}点击数据库以获得p.by,我认为它是对auth.User的ForeignKey。

除此之外,使用无效缓存(首次运行),您将再次在{# 2 #}点击数据库以获取该帖子图像的列表。

因此,对于100个项目,每次初始运行请求时,您将访问数据库201次;对于图像循环,您将使用填充的缓存来访问数据库。

如果可能的话,尝试在帖子查询中使用select_related将这些额外结果添加到一个查询中。像posts = Post.objects.select_related('by', 'images').filter(...)这样的东西可能会起作用,但我知道select_related在反向外键和m2m字段时有限制(它可能不适用于图像,具体取决于你的模型结构)。

答案 1 :(得分:1)

在开发模式中,django做了很多事情来简化开发(例如:代码重新加载;如果使用模板,每个请求的模板呈现; ......)。

在生产模式下,在首选django之前部署WSGI服务器。这样的wsgi可能是gunicornuWSGI,......

典型的生产网络服务器布局可能是:nginx - > gunicorn - > django的

一个简单的比较(django官方教程代码非常简单" Hello World!@ time"模板):

{% block content %}
    <p> Hello World! @ {{ now }}</p>
{% endblock %}

开发模式

直接与django一起运行

  

python manage.py runserver

运行apache-ab进行测试

  

ab -n1000 -c10 http://127.0.0.1:8000/polls/helloworld

Server Software:        WSGIServer/0.2 # django
Server Hostname:        127.0.0.1
Server Port:            8000

Document Path:          /polls/helloworld
Document Length:        59 bytes

Concurrency Level:      10
Time taken for tests:   3.438 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      242000 bytes
HTML transferred:       59000 bytes
Requests per second:    290.87 [#/sec] (mean)
Time per request:       34.380 [ms] (mean)
Time per request:       3.438 [ms] (mean, across all concurrent requests)
Transfer rate:          68.74 [Kbytes/sec] received

生产模式

与gunicorn一起跑

  

../ bin / gunicorn -w4 mysite.wsgi #with 4名工人

运行apache-ab进行测试

  

ab -n1000 -c10 http://127.0.0.1:8000/polls/helloworld

Server Software:        gunicorn/19.7.1  # gunicorn
Server Hostname:        127.0.0.1
Server Port:            8000

Document Path:          /polls/helloworld
Document Length:        59 bytes

Concurrency Level:      10
Time taken for tests:   0.618 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      248000 bytes
HTML transferred:       59000 bytes
Requests per second:    1619.10 [#/sec] (mean)
Time per request:       6.176 [ms] (mean)
Time per request:       0.618 [ms] (mean, across all concurrent requests)
Transfer rate:          392.13 [Kbytes/sec] received