轉自:http://obmem.info/?p=717php
原本我一直不知道怎麼來更好地優化網頁的性能,而後最近作python和php同類網頁渲染速度比較時,意外地發現一個很簡單很白癡可是我一直沒發現的好方法(不得不BS我本身):直接像某些php應用好比Discuz論壇那樣,在生成的網頁中打印出「本頁面生成時間多少多少秒」,而後在不停地訪問網頁測試時,很直觀地就能發現什麼操做會致使瓶頸,怎樣來解決瓶頸了。python
因而我發現SimpleCD在生成首頁時,意外地居然須要0.2秒左右,真真不能忍:對比Discuz論壇首頁平均生成才0.02秒,而Discuz論壇的首頁頁面無疑比SimpleCD的主頁要複雜很多;這讓我情何以堪啊,由於這必然不是Python語言致使的差距,只能說是我徹底沒作優化而Discuz程序優化得很好的後果。mysql
其實不用分析也能知道確定是數據庫在拖累,SimpleCD在生成首頁時須要在sqlite的三個數據庫中進行42屢次查詢,是歷史緣由致使的極其低效的一個設計;可是這40屢次查詢中,其實大部分是很是快的查詢,仔細分析一下就有兩個是性能大戶,其餘都不慢。sql
第一個大戶就是:獲取數據個數shell
SELECT count(*) FROM verycd
這個操做每次都要花很多時間,這是由於每次數據庫都要鎖住而後遍歷一遍主鍵統計個數的緣故,數據量越大耗時就越大,耗時爲O(N),N爲數據庫大小;實際上解決這個問題很是容易,只要隨便在哪存一個當前數據的個數,只有在增刪數據的時候改動就好了,這樣時間就是O(1)的了數據庫
第二個大戶就是:獲取最新更新的20個數據列表緩存
SELECT verycdid,title,brief,updtime FROM verycd ORDER BY updtime DESC LIMIT 20;
由於在updtime上面作了索引,因此其實真正查詢時間也就是搜索索引的時間而已。然則爲何這個操做會慢呢?由於個人數據是按照publish time插入的,按update time進行顯示的話就確定須要在至少20個不一樣的地方作I/O,這麼一來就慢了。解決的方法就是讓它在一個地方作I/O。也就是,除非數據庫加入新數據/改變原有數據,不然把這條語句的返回結果緩存起來。這麼一來又快了20倍:)架構
接下來的是20條小case:取得發佈人和點擊數信息分佈式
SELECT owner FROM LOCK WHERE id=XXXX; SELECT hits FROM stat WHERE id=XXXX;
這裏爲何沒用sql的join語句來省點事呢?由於架構緣由這些數據放在不一樣的數據庫裏,stat是點擊率一類的數據庫,由於須要頻繁的插入因此用mysql存儲;而lock和verycd是須要大量select操做的數據庫,由於mysql悲劇的索引使用狀況和分頁效率而存放在了sqlite3數據庫,因此沒法join -.-memcached
總之這也不是問題,跟剛纔的解決方法同樣,通通緩存
因此縱觀我這個例子,優化網頁性能能夠一言以蔽之,緩存數據庫查詢,便可。我相信大部分網頁應用都是這樣:)
終於輪到memcached了,既然打算緩存,用文件作緩存的話仍是有磁盤I/O,不如直接緩存到內存裏面,內存I/O可就快多了。因而memcached顧名思義就是這麼個東東。
memcached是很強大的工具,由於它能夠支持分佈式的共享內存緩存,大站都用它,對小站點來講,只要出得起內存,這也是好東西;首頁所須要的內存緩衝區大小估計不會超過10K,更況且我如今也是內存土豪了,還在意這個?
安裝:略
配置運行:由於是單機沒啥好配的,改改內存和端口就好了
vi /etc/memcached.conf /etc/init.d/memcached restart
在python的網頁應用中使用之
import memcache mc = memcache.Client(['127.0.0.1:11211'], debug=0)
memcache其實就是一個map結構,最常使用的就是兩個函數了:
因而對一個正常的sql查詢能夠這麼幹
sql = 'select count(*) from verycd' c = sqlite3.connect('verycd.db').cursor() #原來的處理方式 c.execute(sql) count = c.fetchone()[0] #如今的處理方式 from hashlib import md5 key=md5(sql) count = mc.get(key) if not count: c.execute(sql) count = c.fetchone()[0] mc.set(key,count,60*5) #存5分鐘
其中md5是爲了讓key分佈更均勻,其餘代碼很直觀我就不解釋了。
優化過語句1和語句2後,首頁的平均生成時間已經下降到0.02秒,和discuz一個量級了;再通過語句3的優化,最終結果是首頁生成時間下降到了0.006秒左右,通過memcached寥寥幾行代碼的優化,性能提升了3300%。終於能夠挺直腰板來看Discuz了:)
說memcached是妖孽,並非由於memcached應用了以後性能狂升——這本是意料之中的事情,不這樣反而才奇怪——而是由於我基本上沒花多少時間就實現了這麼妖孽的效果,至少我花的時間並不比寫這篇blog的時間多。那麼方便的使用方法和那麼顯著的性能提高情況真是讓人咋舌。