再探 Ruby 效能 Ruby Performance Revisited

作者:周思博 (Joel Spolsky)
SEPTEMBER 12, 2006
屬於 Joel on Software, https://www.joelonsoftware.com/2006/09/12/ruby-performance-revisited/

Jack Herrington 針對 Ruby on Rails 的效能議題寫電郵給我,信上寫著:

我同意你關於 Unicode 的說法,也同意 Rails 需要時間發展。不過我用了一堆的 Web 技術,每個都有問題。 我倒是不同意你對可擴充性(scalability)的說法。我不認為 Rails 有那種其他技術所沒有,而且無法克服的擴充性問題。 我希望你至少能把你對擴充性的說法講得更清楚。告訴我們是什麼樣的擴充性問題。即使我們無法替你解決,整個社群還是能由你的經驗有所收獲。

David Heinemeier Hansson 寫著:

Rails 對絕大多數的 web 應用而言已經夠快了。我們有每天處理數百萬個動態網頁的網站。如果你的目標是做出像 Yahoo 或 Amazon 的首頁,大概沒有基於任何語言的現成框架能做得好。你很可能得自己來。不過當然啦,我也是喜歡讓 CPU 閒一點。不過恰巧的是,我更希望能讓開發者更閒,所以願意犧牲前者來獲得後者。

順便澄清一下,我在意的是 Ruby 而不是 Rails 的效能。原因如下:

我看過許多拿 Java(對我而言不算快)之類的 bytecode 語言和 Ruby 效能對照的比較,而且我也看到很多效能報告聲稱 Ruby 慢十倍慢五十倍云云。除了少數的網誌鬼扯外,Ruby 在電腦語言對抗評比上幾乎是穩吊車尾了。

我並不知道 Ruby 實作的細節,不過我猜最大的問題大概是在晚期連結(late binding)以及最主要的鴨子型別處理(duck typing)吧,有了後者就不能用型別參考或是強型別處理。這表示函數的呼叫一定會慢,因為你永遠沒有辦法把函數呼叫編譯成單一個 x86 指令集的 CALL指令... 你一定得探索物件,甚至可能要掃瞄一個雜湊表才能找到所要呼叫的函數。呼叫物件的方法是個極為常用的操作,在純物件導向的語言中更是如此。有些語言的物件型別可以在編譯時期決定,所以跳躍的指令可以在編譯時得到(如 C 語言),或是透過單一個 vtable 用一個間接指令取得(如 C++ 中)。Ruby 至少得把那一小段程式碼,化簡成一個間接 CALL 的 CPU 指令,才能提供和這類語言相當的效能。

我瞭解開發時間比 CPU 時間更重要的原理,不過坦白說那只不過是保險桿貼紙上的口號,對抱怨效能的人來說並不公平。敝公司的產品 FogBugz 似乎應該很適合用 Ruby on Rails 開發,不過其中還是有些地方的效能極為重要。FogBugz 6 裡就有個地方,得進行數百萬次運算才能在單一個網頁上顯示一個圖表。我們在目前的開發環境下做了許多最佳化,才把運算時間縮到三秒左右。坦白地說,如果是用 duck-typed 函數呼叫的話,我不認為我們能在網頁瀏覽器逾時前或在合理時間內完成。我們也必須用 Bayesian 過濾器掃瞄進入的電郵訊息。這個計算密集的操作過濾一個訊息約要一秒。對我們很多客戶而言,每秒收到一封電子郵件並不算離譜,所以現在的效能非常接近 CPU 運算能力的極限。而這已經是用一種執行這類程式碼比 Ruby 快數個量級的語言了。改用 Ruby 的話我們穩死無疑。

就算是典型單純的 CRUD 應用程式,也就是那種只是由資料庫讀個資料表顯示出來,讓你增刪編輯各筆資料的應用程式,在深入到程式碼某處時,都常會發現某些需要密集運算的動作。比如網誌軟體可能會要用 Bayesian 過濾器來消除垃圾意見。你在這種地方就會突然明白,你所選的語言比競爭者慢上十倍,於是你根本就無法加上該功能,不然就得呼叫另一種語言(並且承受附帶的轉換整編(marshalling)負擔)。

並不是每個人都會遇到這種問題,不過當人們說遇到 Ruby 的效能問題,或僅僅只是想讓程式執行得比核心的 Ruby 語言引擎更快時,Ruby 擁護者唱歌頌讚「開發者時間與 CPU 時間」是沒有用的。就算你不做需要密集運算的東西,如果發現自己得買 100 台伺服器而非 10 台時,你可能就會突然重新思考整個開發者時間與 CPU 時間的方程式。

我瞭解有些計畫要用某種 bytecode 編譯器來處理 Ruby 的效能問題,這很不錯。當這些計畫實現而且 Ruby 也出現具競爭力的效能評比後,對各式各樣的應用可能會更為適合。不過在那之前,我還是會聲稱並非每種狀況都適合使用 Ruby。

這些網頁的內容為表達個人意見。
All contents Copyright © 1999-2006 by Joel Spolsky. All Rights Reserved.