- 論壇徽章:
- 0
|
轉】提高Ruby on Rails性能的幾種技 巧
Ruby on Rails以其高度的易用性和靈活性著稱,不過這些優(yōu)點的背后還存在著性能的隱患。最近,資深Ruby on Rails作家David Berube提供了幾個Ruby on Rails性能優(yōu)化的技巧,對相關開發(fā)人員具有一定的借鑒意義。
Ruby on Rails以其高度的易用性和靈活性著稱,不過這些優(yōu)點的背后還存在著性能的隱患。最近,資深Ruby on Rails作家David Berube提供了幾個Ruby on Rails性能優(yōu)化的技巧,對相關開發(fā)人員具有一定的借鑒意義。
David Berube在文章中首先分析了Rails應用運行緩慢的原因:
Rails總是會做一些假設為您加速開發(fā)。通常,這種假設是正確而有幫助的。不過,它們并不總能有益于性能,并且還會導致資源使用的效率低下——尤其是數(shù)據(jù)庫資源。
另一個顯著的挑戰(zhàn)是N+1問題......這會導致很多小查詢的執(zhí)行,而不是一個單一的大查詢。例如,ActiveRecord無從知道一組父記錄中的哪一個會請求一個子記錄,所以它會為每個父記錄生成一個子記錄查詢。由于每查詢的負荷,這種行為將導致明顯的性能問題。
由于ActiveRecord 能夠讓如此眾多的任務變得輕而易舉,Rails開發(fā)人員常常會形成 “SQL 不怎樣” 的一種態(tài)度,即便在更適合使用SQL的時候,也會避免SQL。創(chuàng)建和處理數(shù)量巨大的ActiveRecord對象的速度會非常緩慢,所以在有些情況下,直接編寫一個無需實例化任何對象的SQL查詢會更快些。
對于如何檢測性能問題, David Berube提供了一些建議:
最好的工具之一是Rails開發(fā)日志,它通常位于每個開發(fā)機器上的log/development.log文件內。它具有各種綜合指標:響應請求所花費的總時間、花費在數(shù)據(jù)庫內的時間所占的百分比、生成視圖所花時間的百分比等。
在生產期間,通過查看mysql_slow_log可以找到很多有價值的信息。
其中一個最強大也是最為有用的工具是query_reviewer插件。這個插件可顯示在頁面上有多少查詢在執(zhí)行以及頁面生成需要多長時間。并且它還會自動分析 ActiveRecord生成的SQL代碼以便發(fā)現(xiàn)潛在問題。例如,它能找到不使用MySQL 索引的查詢,所以如果您忘記了索引一個重要的列并由此造成了性能問題,那么您將能很容易地找到這個列。此插件在一個彈出的
(只在開發(fā)模式下可見)中顯示了所有這類信息。
針對N+1查詢問題,David Berube舉了一個未優(yōu)化的代碼示例:- <%@posts = Post.all(@posts).each do |p|%>
-
- <%=p.category.name%>
-
- <%=p.body%>
-
- <%end%>
復制代碼 David Berube指出,上述代碼生成了一個查詢外加@posts內的每行一個查詢。由于每查詢的負荷,這可能會成為一個很大的挑戰(zhàn)。罪魁禍首是對p.category.name的調用。這個調用只應用于該特定的post對象,而不是整個@posts數(shù)組。這種情況通過使用立即加載可以修復。立即加載(Eager loading)意味著Rails將自動執(zhí)行所需的查詢來加載任何特定子對象的對象。Rails將使用一個JOIN SQL語句或一個執(zhí)行多個查詢的策略。不過,假設指定了將要使用的所有子對象,那么將永遠不會導致N+1的情形,在N+1情形下,一個循環(huán)的每個迭代都會生成額外的一個查詢。優(yōu)化后的代碼如下:- <%@posts = Post.find(:all, :include=>[:category] @posts.each do |p|%>
-
- <%=p.category.name%>
-
-
- <%=p.body%>
-
- <%end%>
復制代碼 比較復雜的情況包括嵌套的立即加載和間接的立即加載。
除了解決N+1問題之外,David Berube還提供了一些優(yōu)化建議:
使用Rails提供的分組和聚合(grouping and aggregate)函數(shù)
用Rails定制 SQL
確保獲得cache-money緩存插件
不過目前動態(tài)語言在企業(yè)開發(fā)中的應用還不夠廣泛,很多企業(yè)只是用它來做一些粘合系統(tǒng)的工作,并沒有承擔起主力開發(fā)語言的重任。尤其是在底層系統(tǒng)開發(fā)方面,動態(tài)語言遠沒有在Web開發(fā)方面那么風光。在運行時效率和虛擬機穩(wěn)定性方面的不足,使得動態(tài)語言注定無法與編譯型語言競爭,并取代它們在高性能領域的地位。然而,動態(tài)語言也有自己的優(yōu)勢所在。如何克服自己的劣勢,將優(yōu)勢發(fā)揚光大,便是每一位動態(tài)語言開發(fā)者所面臨的機遇和挑戰(zhàn)。
我所在的團隊用了近兩年的時間,將一個電信領域的公司絕大部分的生產系統(tǒng)用動態(tài)語言(主要是Python)重寫。包括短/彩信消息網關、業(yè)務訂閱服務、座席查詢系統(tǒng)、銷售支撐系統(tǒng),乃至搜索引擎等多個核心系統(tǒng),都在重寫之列。重寫的理由很多,一方面原有系統(tǒng)無論是從性能上,還是從應對需求變化的能力上,都已經不能滿足業(yè)務發(fā)展的需要;另外一方面,動態(tài)語言的諸多優(yōu)勢,也是我們重寫的動力。這里僅以開發(fā)這些系統(tǒng)時獲得的經驗,來談談動態(tài)語言在應用時的優(yōu)缺點。
標簽: ruby
|
|