Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Sat, 28 Sep
はじめの言語の賞味期限

ライブドアブログの PSGI 化の話 は良いはなしだと思う。一方で、私はあんまり Perl が好きじゃないので、10年にわたって生き続けた Perl アプリケーションが、次の10年にむけてアップをはじめているのは、ちょっとしたホラーでもある。

Twitter と Ruby と JVM

ライブドアブログが、将来に向けて mod_perl から PSGI + Starlet にかえたように、将来に向けてプログラミング言語をかえる人達も存在する。最近の事例で有名なのは、Twitter の Ruby から JVM 言語群への移行だろう。

OSCON Java 2011 の Twitter: From Ruby on Rails to the JVM では、JVM への移行に至った理由として

  • Ability to handle server workloads
  • A real concurrency model

といったよく知られた性能面の問題にくわえて “flexibility in language” をあげている。

Twitter といえば Scala School や、O’Reilly の Programming Scala の共著者で、元 API Lead の Alex Payne, そして Finagle をはじめとする様々なオープンソースソフトウェアなど Scala のイメージが強い。しかし、すくなくとも講演当時は、Twitter の広告まわり、Summize の買収 からはじまる検索まわりなどは Java で書かれていて、さらに BackType の買収から Clojure で書かれている部分もあるらしい。

この当時は Twitter の JVM 化はまだストレージまわりにとどまっていた。唯一の例外が検索まわりで、これについては Twitter Search is Now 3x Faster に詳しい。

さて、Twitter の「移行」には言語の変更だけではなく、Rails 上の大きな一つのソフトウェアを、JVM 上で動く、複数の小さなソフトウェアの集合に構成し直すという、アーキテクチャ的な変更がふくまれている。QCon New York 2013 の Decomposing Twitter: Adventures in Service-Oriented Architecture では Twitter のアーキテクチャの概要と、講演者の Jeremy Cloud が Tech Lead をつとめる Tweet Service についての詳しい説明、SOA 化にともなうインテグレーションテストの困難と、それをなんとかするための工夫など、様々な話題について触れられている。

この講演では Rails からの移行の理由 (Rails 時代に直面した問題) として

  • Storage I/O bottlenecks
  • Poor concurrency, runtime performance
  • Brittle (ひとつの問題でサイトの全体がダウンする可能性がある - 実際あった)
  • Too many cooks in the same kitchen (開発者同士の変更が diff 的にも意味的にも衝突する)
  • Lack of clear ownership
  • Leaky abstractions / tight-coupling

と、性能だけではなく、開発や組織面での問題にも触れているのが面白い。講演の主題の差もあるんだろうけど、2011年と2013年の違い – Twitter の SOA 化が進んだ上で、ふりかえって問題だったと認識できた部分もあるんじゃないかと思う。

Twitter を外からのトラフィックをうける部分から順にルーティング、プレゼンテーション、ロジック、ストレージの4層に分割すると、前述した通り、2011年ごろの Twitter の JVM 化 (SOA 化) はストレージ部分だけに留まっていた。のこりの部分は Rails アプリケーション (“Monorail” と呼んでいる) がすべて処理している。

現在の Twitter では、Monorail の役割はだいぶ縮小している。ルーティング層には “TFE” と呼ばれるリバースプロキシが存在し、Monorail はプレゼンテーション – ロジックにまたがる形で一部 (全体トラフィックの30%から40%程度) をうけている。のこりのトラフィックは、プレゼンテーション層に API, Search, ロジック層に Tweet Service, User Service, Timeline Service と小さく分割されていて、どれも複数の層はまたがない。なお、TFE からプレゼンテーション層への通信には HTTP を、それ以外の層をまたぐ通信には Thrift を使っているらしい。

High Scalability の Tumblr Architecture - 15 Billion Page Views A Month And Harder To Scale Than Twitter によると、Tumblr も同じような歴史をたどっているようだ。はじめにあった PHP アプリケーションの機能は徐々に Scala + Finagle で出来たサービスに移譲され、元のアプリケーション部分はサービスを叩くだけの薄いものになっていく。

Facebook の PHP への投資量

はじめに使いだした言語自体にひたすら投資しているのは、なんといっても Facebook だろう。

2010年2月に、Facebook は HipHop という PHP から C++ への変換ソフトウェアを公開する。

HipHop for PHP: Move Fast

HipHop programmatically transforms your PHP source code into highly optimized C++ and then uses g++ to compile it. HipHop executes the source code in a semantically equivalent manner and sacrifices some rarely used features — such as eval() — in exchange for improved performance. HipHop includes a code transformer, a reimplementation of PHP’s runtime system, and a rewrite of many common PHP Extensions to take advantage of these performance optimizations.

Velocity 2011 の Facebook Open Compute & Other Infrastructure (5:23 ごろ) によると、当時 Facebook には3つの PHP ランタイム置き換えプロジェクトがあったらしい。PHP の C 実装の部分的書き換え、PHP の Java 実装である Quercus を使うもの、そして HipHop だ。この3つのプロジェクトは並行にはじまり、結局 HipHop が生き残ることになった。

アプリケーションプログラマが手元で動かすために、HipHop ベースのインタプリタである HPHPi もあわせて開発された。HPHPi はもともとそんなに速くはなく、2011年10月の Making HPHPi Faster ではその高速化にふれられている。

さらに 12月、Facebook は HipHop ベース JIT つき仮想マシン、HHVM を発表する。

The HipHop Virtual Machine

So, early last year, we put together a small team to experiment with dynamic translation of PHP code into native machine code. What resulted is a new PHP execution engine based on the HipHop language runtime that we call the HipHop Virtual Machine (hhvm). We’re excited to report that Facebook is now using hhvm as a faster replacement for hphpi, with plans to eventually use hhvm for all PHP execution.

2012年11月の Speeding up PHP-based development with HipHop VM では HHVM による実行が C++ へ変換したコードなみに速くなったこと、それに伴う、本番環境の HHVM への移行にふれられている。

Facebook の PHP への投資はまだつづく。CUFP 2013 の Facebook: Analyzing PHP statically と Strange Loop 2013 の Taking PHP Seriously によると、彼らは型のついた PHP 方言である Hack という言語を開発し、すでに本番で使いはじめているらしい。

動画がまだない (InfoQ で公開されているもの は Strange Loop 参加者以外はまだアクセスできない) ので全貌はわからないものの、Strange Loop の発表スライド と、Liveblogging CUFP 2013 だけでも、かなり信じがたいことが書いてある。

Strange Loop のスライドによると、Hack は PHP の文法そのものを拡張し、メソッドの引数や戻り値の型を明示できるようにした言語と、それに対する静的なチェックを行うソフトウェアで構成されるようだ。サンプルコードはこんな感じ。

<?hh
...
function meanOrigDistance(Point $p, Point $q)
  : float {
  $distf = function(Point $p) : float {
    return sqrt($p->x * $p->x + $p->y * $p->y);
  };
  $pdist = $distf($p);
  $qdist = $distf($q);
  return ($pdist + $qdist) / 2;
}

面白いのは Hack の型を HHVM は見ておらず、型検査が開発効率をあげるためだけに存在しているところだ。ここは TypeScript のような AltJS に似ているかもしれない。 Facebook のほとんどの新しいコードは Hack で書かれ、Facebook のほとんどの PHP 開発者はつねに Hack でコードをチェックしているらしい。

CUFP では、Hack が OCaml をつかって実装されていると説明されている。そういえば Facebook の pfff には OCaml で書かれた PHP parser があったはずだ。Julien Verlaguet さんの GitHub アカウント からたどってみると

など Hack で書かれたソースコードむけにすこし拡張されていた。Hack もこの parser を使っているのだろうか。

ただ、Facebook の PHP への過剰な投資は、Facebook が 100% PHP で書かれていて、バックエンドもフロントエンドもない一枚岩のシステムであることを、必ずしも意味しない。Facebook が開発した RPC ライブラリである Thrift は (オープンソースで他の人々からの協力もあるとはいえ) 複数の言語に対応しているし、Erlang at Facebook では Facebook Chat における Erlang の説明以前に、エンジニアリングチームの特徴として polyglot programming を自称している。

まとめ

将来にむけたプログラミング言語選択の例として、Rails 上の大きなアプリケーションから、JVM ベースのサービス指向アーキテクチャへの移行をすすめる Twitter と、ほかの言語もあるんだろうとはいえ、絶対量でみるとかなりを PHP に投資しているようにみえる Facebook について紹介しました。

ほんとうは「JVM や CLR のような複数の言語から使える実行環境 + ライブラリ群や、Thrift のような RPC を使えば、年代物のソフトウェアに新しい言語を混ぜ込むのは不可能じゃない。普段コードレビューだなんだとソフトウェアの良し悪しに議論している人達が、ことプログラミング言語の話になると『お互いに良いところを取り入れていけばいい』『プログラミング言語は大きな問題じゃない』みたいなことをいうのは処世術の一種なので鵜呑みにしてはいけないよ。」ということを書きたかったんだけど、Facebook の鮮烈さにすこし負けた感じがします。

2013年10月3日追記

公開した時は Strange Loop スライドの25ページ目 (“Hack Implementation”) の図と、最後の 39ページ目 (“Everyone’s favorite generics slide”) にある

Remember, runtime throws everything away anyway, so perfwise, it’s type erasure.

から

面白いのは Hack の型を HHVM は見ておらず、型検査が開発効率をあげるためだけに存在しているところだ。ここは TypeScript のような AltJS に似ているかもしれない。

と書いていたのですが、ここは確証がもてないので取り消します。すくなくとも HHVM の parser (hphp/parser/hphp.y) は読んでいて、HPHP::MethodStatement#retTypeAnnotation までは渡っているようにみえます。