土曜日, 3月 07, 2009

[Scala] Twitterの移行について

ずいぶん前の話題だが、TwitterのバックヤードScala化に関する記事の要点整理をしてみた。

>>前提

Twitterは、フロントはRailsに依存しており、逆にOffload観点から、キャッシュの失効処理等に、キューイングの仕組みを使った非同期処理が多数あり、それだけデーモンアプリが必要となるシステム構成。

>>なぜ移行?(システム的理由)

RubyはGreenThreadでカーネルスレッドを使うことはできず、プロセッサに依存してしまい、マルチコア環境での性能が出ない。これに対処するため複数プロセスを上げる方向に行くのだが、そうなるとメモリが大量に必要となり、さらにRubyのガベコレ性能が(Javaのそれに比べて)悪いこともあり、限界を感じていた。

(これに対し)JVMは、スクリプト言語が苦手とする長時間動かし続けるデーモンアプリを書く環境として適切。

また、動的型付けにより必要となる「型確認」の計算量が莫大になっていたという問題もあった。たとえば障害復旧時の処理時間が長くなりすぎていた。

JRubyへの移行も考えたが、オリジナルレベルのパフォーマンスは出ないこと、またそもそもRailsが動かなかったことから不採用とした。ただし将来的に再考の余地はあると考えている。

パフォーマンスという観点では、mutableとimmutableに注意すること。JITコンパイラはimmutableなオブジェクト(状態変化がない≒必然的にスレッドセーフとなる)であれば、最適化してゆくことができる。

>>なぜ移行?(その他の理由)

これまでのエンタープライズな職場を去ったあと、楽しく書いてゆきたい(表現してゆきたい)という理由から、(書いていてつまらない言語(C++など)を卒業し)Ruby等の高級言語に転向するプログラマをたくさん見てきた。

>>移行してどうだったか

とても上手くいった(性能向上及び動作安定化の観点から)。

静的型付けは、(Rubyでもわざわざ型宣言を使っていた位だから)まったく手間ではなかった。

actor部分とハイスケーラビリティを確保するところでいくつか問題が出たが、致命的なものはまったく無かった(良い意味で想定外)。

actorでの並列処理の記述はクライアントからの接続を受ける部分などを中心に極めて有効であった。

(中を再考している過程で)逆にactorまでは必要とせず、逆にthreadのほうが適している場合もあることが分かった。そしてこのときでも、(actorを)threadに書き戻すことは置換するレベルでありとても簡単だった(書き換えでいうと、普通にlockすればいいだけという場合も)。

いくつかパフォーマンス観点からJavaのクラスを直接利用する場面があったが、このようなことができることもScalaの利点だ。

>>切り替えで気をつけることは

関数型という考え方になれること(メンタリティ)。ただしこれは使っているうちに慣れてくる部分が大きい。その意味でもすぐにビジネスが絡むシステムに使うのではなくスタートアップで利用してゆくべき。

(型やその中身ベースでの)パターンマッチを使いこなせることは、効率的記述を行うためにとても重要だ。

IDEがモノによっては(Scalaの)サポートが完全ではないため注意が必要。TwitterではIntelliJとEmacsのそれを使っている。

インタプリタではなくcompile-deployが必要になることも、(慣れの問題かもしれないが)いらいらさせる原因となりうる。この点はProjectごとにケアが必要だとはいえ、JavaRebelを使えば解決できる。

>>その他

Scalaを選択する決断をするまでには煩悶してきた。でも(Rubyを使ってきた我々が)C++などの中級言語に移行することは、とても大きなリスクを負うことになり、かつ困難を伴うと判断した。

2009年度内には、メインどころのトラフィックを稼いでいるAPIをScalaベースに切り替える予定。