2012-02-07 36 views
13

說,我有一個帶有照片庫的頁面。每個縮略圖例如具有照片,國家,作者等等。我使用模板標籤(它加載指定的模板)渲染這些項目/小部件 - 因爲DRY(我在頁面上的不同位置單獨使用這些項目/小部件)而這樣做。Django - 使用templatetags呈現很多模板很慢

而且速度很慢。

我一直在使用的Django調試工具欄進行一些剖析:

SQL Queries: default 84.81 ms (147 queries) 

但是:

Total CPU time: 5768.360 msec 

這是等待太久。

經過一番分析發現,主要的罪魁禍首是模板工程。

當我想顯示例如150張照片,600個相關項目/小部件正在通過模板呈現。這意味着600個I/O操作甚至更多。將這些小部件移至主模板可解決問題,但不保留DRY。

所以我的問題是如何可以避免這種行爲?是幹還是慢或者不幹幹快? 我寧願乾和快...

+0

你能提供模板標籤代碼嗎? – 2012-05-01 17:24:56

+0

在查詢上花費的時間相對較少。但是,ORM需要更多時間來生成這些查詢並將結果解析到模型實例中 – 2012-05-01 17:27:38

回答

11

經過幾個小時的分析和搜索...

感謝您的幫助,但在這種情況下,我認爲最好的解決辦法,到目前爲止是使用Template fragment caching

我試了一下,並獲得70%-80%的速度性能!

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

你可能想嘗試caching template loader,django.template.loaders.cached.Loader - 它應該肯定會減少所需的IO數量。

編輯即可添加您需要小心以爲只是因爲大部分時間都花在模板渲染階段,查詢計數不是責任。不要忘記,查詢集是懶惰的,除非您在視圖中專門對其進行切片或迭代,否則只會在加載模板時對其進行評估。我會說,通過使用select_related和其他技術來減少查詢數量應該是非常有幫助的。

+0

謝謝。它將其減少到5054.582毫秒,這大約增加了11%。然而,渲染仍然需要5秒的時間。還有什麼可以做的呢? – laszchamachla 2012-02-07 19:57:44

+1

它如何在第二頁加載中執行? – 2012-02-07 20:05:04

+0

同樣 - 最少5秒。 – laszchamachla 2012-02-07 20:07:52

4

我假設你使用的調試工具欄,你正在開發中獲得這些數字。但是,正因爲如此,這些並不是「真正的」數字。

內置的Django服務器對開發很有好處,但它有一些缺點,使得比真實的網絡服務器要慢得多。首先,它是單線程的,所以這意味着沒有並行請求。這也意味着IO操作是離散的。其次,它的任務不僅僅是向Django提供請求,還包括靜態資源。

總而言之,如果你想真正地分析你的網站的頁面加載時間,你需要在本地安裝一個真正的網絡服務器。基本上像你在生產環境中那樣設置它。我願意投注的時間將是遠遠更好,那麼。

+1

從Django 1.4開始,注意到runserver是線程化的,所以它可以處理並行請求 – Izkata 2013-11-07 16:33:50

0

這可能不適用於此特定問題,但在某些情況下,它幫助我在查詢上使用select_related。可能不是這樣,但它可能會降低您的查詢計數。

+0

select_related不是拋出84ms查詢集的東西。這是關於模板。 – jstaab 2014-07-25 19:05:33

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 

所以,你templatetag裏面你不必詢問意見數爲一張照片,但你已經在comments_count屬性信息。並且您在一個查詢中實現了這一點。

0

我有同樣的問題,也許出於同樣的原因。我優化了自定義模板標籤的性能。數據庫請求的數量從640減少到2,結果數據庫時間低於20毫秒。但是我的頁面變慢了! 7s - > 10s。嘆。我嘗試了一個緩存模板加載器,沒有效果。

我已經放棄了,禁用了django調試工具欄,之後響應時間降到了1.2s,令人難以置信!在我的情況下,巨大的響應時間只是由調試工具欄造成的!相關問題可以在here找到。在這個工具欄問題上,我並沒有深入,因爲我打算使用模板片段緩存來緩存模板標籤。在開發過程中,我每隔15分鐘就有10秒的響應時間,這是我可以忍受的。無論如何,希望這有助於。