2007年8月10日 星期五

Ruby on Rails的效能低落

儘管我是寫Rails的,寫了想想也快要一年了。東看西看都覺得這實在是一個好東西,不過反過來,當我們的服務要上線的時候。組長卻說我的benchmark test case不夠好,不能夠測出很準確的數值(或許他心想這太好了,三台準系統可以跑200多個request/sec)。

是的, 我是多半隱藏了這個缺點,甚至很不想要去說「對,他就是一個這樣慢的東西」。當一堆文章都在寫說mongrel或是lighttpd cluster有多快,我心裡總是想著apache+mod_fcgid(你知道我在說哪一個blog...XD),我們的目標是做上萬人使用的系統,總不能真的去跑mongrel吧?那跟跑webrick有啥不同?



我是這樣想的,當然參考是相當必要的。

http://blog.kovyrin.net/2006/08/28/ruby-performance-results/

在這樣的情況之下,不管如何還是決定採用haproxy。而交叉測試的結果,也證明haproxy比apache稍快,而這樣的結果也是合理的。而進行服務的也還是選擇apache+mod_fcgid。

但是在今天的測試,只是稍微從列出2個人,改成列出20個人, 就從200 req/s降到35req/s,實在讓我太訝異!我發現問題不是在ActiveRecord連DB要時間,而是render的時間爆衝,之前就聽說partial很吃效能,早就不敢多用,乖乖寫在迴圈裡。但實際上跑完profiler後,我想是沒錯的...

Requests per second: 12.98 [#/sec] (mean)

其實根本整體就很慢,連跑個array.each_index都小吃效能。 最後將這個function改回array.each,以ab -t 30 -c 100 跑在intel雙核2.8G,2G RAM,就是這個結果了。與以往在爛p4上測沒啥太大不同。此外也學到一個經驗是ab不要連續跑太多次,apache需要有些時間做GC,那時會很慢。

而將-c 降到10之後,約是可以接受的回應速度:

Percentage of the requests served within a certain time (ms)
50% 634
66% 776
75% 979
80% 1048
90% 1330
95% 1570
98% 1939
99% 2090
100% 3420 (longest request)


如此表示,這樣一台兩萬塊的機器機器只能夠略估服務1000人而已,說起來像黑米這樣就拿來直接做正式服務的勇者們還真是厲害啊...

因為做了cluster,session一定要放在遠端機器,我就開始測試關掉ActiveRecordStore的數值:

Requests per second: 12.60 [#/sec] (mean)

看來也沒比較好@@

4 則留言 :

  1. 我也是写rails程式的,同样"東看西看都覺得這實在是一個好東西".
    我们主管大大也是写rails程式的.
    听他自言自语了好几次了:ruby很耗资源呀...

    回覆刪除
  2. 不過最後我又用三台clutser跑了一次,其實大概要到-c 80 ~ -c 100的時候才真正開始感覺很慢,表示我們的系統可以撐8000~10000人左右。

    終究這是ruby+rails...希望未來可以有compiler將所有程式都編譯成binary。

    回覆刪除
  3. Ruby慢是很合理的,也不讓人意外。

    不過對於買Server提升效能的做法,我覺得這是從未成熟轉往成熟領域的一種過程。當Server和軟體之間可以有各自提升效能的辦法,而不是一團東西混在一起調校。

    還有另一個議題,就是網站的動態部份真的需要這麼多嗎?我覺得這是cache帶給我們的另一番思考,不能cache的動態不一定會有大量的request,如果有就應該要思考如何解決這問題。經過cache的部份,效能就等於是apache本身的能力。

    我覺得Ruby Rails帶來的好處是有效的將許多問題做拆解,讓你可以各自去提升效能。這也只是以我現在的程度看到的想法。

    回覆刪除
  4. 這幾天思考了一下,Rails的瓶頸是在它的運作慢,和資料庫的連線效能。所以Cache引進的概念是盡量不要讓Request進到Rails裡面。所以我在想Rails裡面不要做可以丟到Client做的工作,舉個小例子來解釋一下。
    像很多人會去做paging,是利用讀取部份的資料給client。但如果一口氣將所有結果丟給client,然後分頁是在client做的,這樣這個頁面可以用page cache,靜態的處理資料應該速度是很快的(這就有點不負責任了,我沒試過)。
    我的概念就是想說,假設動態的部份有四個使用者A, B, C, D其中所有的資料聯集為E,那我就是把E全部丟到Client,然後在Client在去分,當然如果是涉及不想讓其個使用者之間讀取到互相的資料,當然就不能這樣做,不過我的想法是在盡量減少Rails中的負擔,把能夠給Client做的就分離出去。

    然後也還蠻想了解一下你的Javascript+json+rails的做法。

    回覆刪除