再びRubyのパフォーマンスについて

From The Joel on Software Translation Project

Jump to: navigation, search

Joel Spolsky / 青木靖 訳
2006年9月12日 火曜


ジャック・ヘリントンがRuby on Railsのパフォーマンスの問題について私にメールをくれた。

Unicodeの問題は認める。Railsにはまだ成熟のための時間が必要だということも認める。私はたくさんのWebテクノロジーを使っているが、どれも何らかの問題は持っているものだ。
しかしスケーラビリティの話には同意できない。Railsに回避できないようなスケーラビリティ上の問題があるとは思わない。
私がお願いしたいのは、君のスケーラビリティのコメントに、少なくとも説明を付けてほしいということだ。そのスケーラビリティの問題について教えてほしい。たとえ私たちがそれを直せなかったとしても、コミュニティ全体が君の経験から何か得ることはできる。

デビッド・ハイネマイヤ・ハンソンはこう書いている。

Railsは大半のWebアプリケーションのためには十分速い。私たちは1日に動的ページビューが何百万にもなるサイトを作っている。YahooやAmazonのフロントページを作ろうとしたら、どんな言語で書かれていようと、出来合いのフレームワークを使ってうまくいきはしないだろう。おそらくは自分で書く必要がある。確かに私もCPU時間を減らしたいが、しかし私は開発者の時間の方がずっと気にかかる。後者のためであれば喜んで前者を犠牲にする。

議論をはっきりさせるため、Railsのパフォーマンスについては置いておくことにする。私が懸念しているのはRubyのパフォーマンスなのだ。それについて説明しよう。

Rubyのパフォーマンスを、私自身遅いと感じているJavaのようなバイトコード言語と比較したレポートをたくさん見てきたが、その多くでRubyの方が10倍遅いとか、50倍遅いとか報告されている。そこら中のブログで書かれていることを別にしても、"Computer Language Shootout Benchmarks"でRubyはほとんど最下位になっている。

Rubyの実装についてはあまり知らないが、おそらく一番の問題はレイトバインディングとダックタイピングにあるのだと思う。これは型推論と強い型付けを妨げるため、関数呼び出しは常に遅いものになる。関数呼び出しを単一の(x86の)CALL命令にまで落とし込むことが決してできないからだ・・・常にオブジェクトを探す必要があり、おそらくはハッシュテーブルをスキャンして呼びたい関数を見つける必要がある。オブジェクトのメソッドを呼び出すというのは、純オブジェクト指向言語では甚だ頻繁に行われる。(Cのように)オブジェクトの型がコンパイル時に決定され、飛び先の命令がコンパイル時に決まる言語や、(C++のように)1個のvtableで1段階間接化される言語と同じパフォーマンスをRubyで得られるようにしようと思うなら、メソッド呼び出しをどうにかして間接的なCALLに変換する必要がある。

開発者の時間がCPUの時間よりも重要だという思想は理解できる。しかし率直に言ってそれはパンパーに貼り付けたスローガンに過ぎず、パフォーマンスに苦情を言っている人たちに対してフェアでないだろう。Ruby on Railsは私たちの製品であるFogBugzに、それこそにぴったりなのかもしれないが、パフォーマンスが非常に重要になる部分がいくつかあるのだ。FogBugz 6には1つのページの1つのチャートの表示に、文字通り何百万もの演算が必要になるところがあり、多くの最適化をほどこして、私たちの開発環境で3秒かそこらにまで持っていったが、ダックタイピングの関数呼び出しを使っていたら、Webブラウザがあきらめてタイムアウトし、太陽が2度ほど傾くまで計算が終わらないだろう。私たちはまた受信メールからスパムをスキャンするのにベイジアンフィルタを使っている。これには多量の計算が必要となり、1通に1秒かかることもある。私たちの顧客の多くにとって、1秒に1通メールを受け取るのは別に珍しいことでもないため、CPUは上がりっぱなしになる。Rubyより数桁速い言語を使ってそうなのだ。Rubyを使っていたら死んでいるよ。

よくある単純なCRUDアプリケーション——基本的にデータベースのテーブルを表示して、レコードの追加、削除、編集ができるようにするアプリケーション——でさえ、やりたいことが高度に計算中心となる場合がある。たとえばブログソフトウェアにコメントからスパムを除くためのベイジアンフィルタを追加したいと思うかもしれない。そして突然気付くことになるのだ。あなたの使っている言語が競合のものより10倍遅いなら、その機能の追加は単に不可能になるかもしれない。あるいは(マーシャリングのオーパヘッドをかけて)別な言語を呼び出さなければならないかもしれない。

これがすべての人に当てはまるというわけではないが、Rubyにパフォーマンスの問題があると人々が言うとき、あるいはコアのRuby言語エンジンが動かせるよりも速くコードを実行できる必要があるというとき、Rubyの支持者たちが「開発者の時間 対 CPU時間」の賛美歌を歌っているのは何の助けにもならない。計算中心となることをやっているのでなかったとしても、10台のサーバの代りに100台のサーバを買わなければならないと気付いたときに、急遽「開発者の時間 対 CPU時間」の議論に舞い戻ることになるだろう。

ある種のバイトコードコンパイラを使ってRubyのパフォーマンスの問題に対処するプランがあるのは知っているし、それは結構なことだと思う。それが実現され、Rubyが高いベンチマークを出すようになったときに、Rubyは今よりもずっと多くの種類のアプリケーションに対しずっと適切なものになるだろう。それまでは、私はRubyがすべての状況に適するわけではないという主張を続ける。


(オリジナル: Ruby Performance Revisited)


メソッド呼び出しの最適化

2006年9月12日 火曜

Avi Bryantがメソッド呼び出しを非常に高速化する方法について書いており、それはダックタイピングしている場合でも使える。クール!

(Rubyはそれでも遅い。詳しいことは後ほど。)


(オリジナル: Optimizing method calls)

戻る

Personal tools