motion-mode.el : RubyMotion の補完を Emacs で

みなさん RubyMotion 書いてますか! 僕は上々です!

最近は割とまっとうに活動しているのでドラゴンクエスト10バージョン1.3 の新職業は全然レベルが上がりません。バトルマスターはまだレベル 53 です。仕事とゲームの両立って難しいですね、参っちゃいますね。

それはそうと、RubyMotionXcode を使わなくても iOS 開発ができるというのが非常に嬉しいところなのですが、Emacs であの長ったらしい Cocoa API の補完をどうするかというのは積年の悩みでした。いちおう gtags を使って補完するみたいなバッドノウハウがあったりしますが、うまく動かなかったりで結局ちゃんと補完できてる人は周りにはいなかった。挙げ句には RubyMotion の補完それだけのために Sublime Text 2 に浮気する連中まで出る始末。

Emacs 界の終わりや!「誰か!救世主はよ!! (他力本願寺)」と言っていたら現れました、救世主ことメシア。

@ainame さん。あんたは神や、後光が差してるで・・・

なんだかおかしなテンションになってしまいましたが、気を取り直してインストールしてみました。motion-mode.el は auto-complete を使って RubyMotion の API を補完してくれる。

http://cdn.bloghackers.net/images/20130322_112430.png

ばっちりじゃないですか。補完が効かないせいでよく大文字小文字やスペルミスしてはまっていたのでこれでだいぶ捗る!ありがとう @ainame さん!アンタの事は忘れないよ!! 昨日会ったし!!

えー、インストールには辞書の生成などちょっと下準備があるので github の README.md をちゃんと読みましょう。

なお、昨日の RubyMotion もくもく会で他にも何人か導入を試みていましたが、auto-complete をちゃんと設定できてないとかではまってる人多数。motion-mode.el を入れる前に一度 auto-complete がきちんと動くように設定を見直してみることをオススメいたします。

今後はキーバインドでビルドやテストが走る追加機能を予定している、とのこと。

これでバーボン片手に「Sublime Text 2 のヤツに Emacs の変わりは重荷だぜ・・・俺の体が覚えたキーバインドがそれを許さねえ。はぁ? vim ? 100万回消滅しろ!!」とか言ってる連中も安泰です。ちなみに自分はそんなに過激派ではないです。

RubyMotion Kaigi 2013 開催

・・・と、Sublime Text や Emacs あるいは RubyMine など周辺ツールも揃ってきて盛り上がりを見せている RubyMotion ですが Ruby Kagii 2013 ではなんと開発者の Laurent Sansonetti さんのトークがあるそうです。そして、Laurent さんが来日するなら併せて "RubyMotion" Kaigi をやろう、といったらほんとに実現してしまいました。もちろん Laurent さんの基調講演もあるよ。ワー、パチパチ。

どしどしご応募ください! と思って書いてたのにすでに定員が埋まっていた!! そして定員枠を広げたとおもったらそれも埋まっていた!!! な、なんだってー。RubyMotion の<鼓動>を感じるぜ・・・。

         ,. -‐'''''""¨¨¨ヽ 
         (.___,,,... -ァァフ|          あ…ありのまま 今日 起こった事を話すぜ! 
          |i i|    }! }} //| 
         |l、{   j} /,,ィ//|       『RubyMotion Kaigi を募集開始したと思ったら締め切っていた』 
        i|:!ヾ、_ノ/ u {:}//ヘ            
        |リ u' }  ,ノ _,!V,ハ |   
       /´fト、_{ル{,ィ'eラ , タ人        な… 何を言ってるのか わからねーと思うが 
     /'   ヾ|宀| {´,)⌒`/ |<ヽトiゝ        おれも何をされたのかわからなかった… 
    ,゙  / )ヽ iLレ  u' | | ヾlトハ〉 
     |/_/  ハ !ニ⊇ '/:}  V:::::ヽ        頭がどうにかなりそうだった… 
    // 二二二7'T'' /u' __ /:::::::/`ヽ 
   /'´r -―一ァ‐゙T´ '"´ /::::/-‐  \      いつまで経っても定員に到達しない某勉強会とか某勉強会とか
   / //   广¨´  /'   /:::::/´ ̄`ヽ ⌒ヽ     そんなチャチなもんじゃあ 断じてねえ 
  ノ ' /  ノ:::::`ー-、___/::::://       ヽ  }        
_/`丶 /:::::::::::::::::::::::::: ̄`ー-{:::...       イ    もっと恐ろしい、RubyMotionの胎動を味わったぜ…  

・・・すいません、すいません。間に合わなかった皆様方におかれましてはぜひキャンセルをお待ちいただければと思います・・・。

Treasure Data

少し前にログの話を書いた http://d.hatena.ne.jp/naoya/20130219/1361262854 ときに、Treasure Data については後日にもう少し詳細に書くと言ったので書くとしよう。

近頃 Treasure Data (以下、時折 TD) という名前をちらほら聞いたことがある人は多いのではないかと思います。「ビッグデータクラウドサービスである」とか「日本人が創業したシリコンバレーベンチャー」、あるいは Yahoo! 創業者の Jerry Yang が投資したとか、Fluentd と何か関係があるといった文脈などなど。

けど、具体的に Treasure Data がどういうサービスで、どういう機能を持っていて、どんな場面で利用されるものなのかはまだあまり良く知られていないかもしれない・・・ようにも見える。今日はその辺から少し紹介していこうかなと思う。

Treasure Data が提供するサービス

本当にごくごく単純化して言うとTDは「手元のサーバーとかからログをどんどん送りつけておくとそれを保存しといてくれて、SQL を投げると MapReduce で大規模並列にそれを実行して結果だけ返してくれるクラウドなサービス」です。

自分は個人でも TD を利用しているのだけど、例えば amazlet というずいぶん昔に作ったウェブアプリケーションのログ、アクセスログにすこし情報を加えたものなんかを TD に送り続けている。OSX にインストールした td コマンドで、TD のサーバーにステータスを問い合わせる。

% td tables nginx
+----------+--------+------+---------+--------+---------------------------+--------+
| Database | Table  | Type | Count   | Size   | Last import               | Schema |
+----------+--------+------+---------+--------+---------------------------+--------+
| nginx    | access | log  | 2649812 | 0.1 GB | 2013-03-22 17:01:57 +0900 |        |
+----------+--------+------+---------+--------+---------------------------+--------+

ま、そんなに大した規模のデータではないけど。とはいえこれでも月間数万人くらいのユーザーはいる。

さて、この送り続けたログから直近一ヶ月くらいの間に、amazlet で紹介された Amazon の商品を計算してみよう。

% td query -w -d nginx "select v['asin'] as asin, count(1) as cnt from access group by v['asin'] order by cnt desc limit 100"

td コマンドで SQL (っぽい) クエリを送信する。すると

Job 2131709 is queued.
Use 'td job:show 2131709' to show the status.
queued...
  started at 2013-03-22T08:07:49Z
  Hive history file=/mnt/hive/tmp/1624/hive_job_log__1111533064.txt
  Total MapReduce jobs = 2
  Launching Job 1 out of 2
  Number of reduce tasks not specified. Defaulting to jobconf value of: 12
  In order to change the average load for a reducer (in bytes):
    set hive.exec.reducers.bytes.per.reducer=<number>
  In order to limit the maximum number of reducers:
    set hive.exec.reducers.max=<number>
  In order to set a constant number of reducers:
    set mapred.reduce.tasks=<number>
  Starting Job = job_201301150013_218289, Tracking URL = …
  2013-03-22 08:08:18,702 Stage-1 map = 0%,  reduce = 0%
  2013-03-22 08:08:26,779 Stage-1 map = 26%,  reduce = 0%
  2013-03-22 08:08:29,814 Stage-1 map = 41%,  reduce = 0%
  2013-03-22 08:08:32,858 Stage-1 map = 58%,  reduce = 0%
  2013-03-22 08:08:35,907 Stage-1 map = 72%,  reduce = 0%
  2013-03-22 08:08:38,935 Stage-1 map = 83%,  reduce = 0%

こんな感じでネットワークの向こう側で MapReduce 計算が始まって処理が行われる。初めて実行したときは手元のOSXからコマンドを送るだけで、インターネットを通じて MapReduce を実行してるなんて・・・! とちょっとした高揚感があったりした。

で、結果はそのまま標準出力に返ってくる。

| B00BHAF688 | 307 | ⇒ ジョジョ (PlayStation 3)
| B00BHO0FK8 | 274 | ⇒ Evangelion Q の Blu-ray
| B009GSX0A4 | 147 | ⇒ 閃乱カグラ (PSP Vita)
| B00A64CFIK | 136 | ⇒ 初音ミク (PlayStation 3)
| B00APVDHLI | 134 | ⇒ ジョジョ (PlayStation 3)
| B0095D6I86 | 128 | ⇒ メタルギア ライジング (PlayStation 3)
| B00BIYSEFA | 123 | ⇒ 真・女神転生IV (Nintendo 3DS)
| B00AHA5OCC | 113 | ⇒ SOUL SACRIFICE (PlayStaion 3)
| B00BIYSF7C | 112 | ⇒ サモンナイト5

矢印以降は自分が補ったもの。どうやら amazlet はゲームソフトを紹介するのなんかによく使われて、直近一ヶ月くらいは PS3ジョジョエヴァンゲリオンの映画の Blu-ray が人気だった・・・なんてことがわかった。ここでは割と単純なクエリを投げているけど、いろんなデータと紐づけてもっと複雑なクエリを実行させたとしても、そこは MapReduce なんで I/O リソースも CPU リソースもリニアにスケールするようになっている。

この例のケースの場合、送っているデータはせいぜいまだ数百MB程度なので何も Treasure Data を頼らなくても MySQL や MongoDB でも十分処理できる。でもポイントはそこではなく、たとえデータが 数百GB や TB オーダーになってもオペレーションとしては何らかわらない、つまりスケーラブルである、というところなのはいわずもがな。

途中、ジョブの経過出力に Hadoop や Hive なんて単語がちらほら見える通り、TD は MapReduce の実行基盤としての Hadoop、それから SQL 風の言語 (HiveQL) で Hadoop 上のデータを操作できる Hive、それらを使って構築されている。また後でもうすこし触れるけれども、実際には単なる Hadoop + Hive のホスティングではなくデータを受け付ける部分、データを保存するストレージ、マルチテナントのジョブを分配するスケジューラ、あるいは結果を返す各種 API などは TD 社が独自に開発したものでまかない全体を統合し、この「ログをがんがん送りつけておいて好きなときに SQLMapReduceできる」というユースケースを提供する。

これが Treasure Data というサービス・・・ということになります。

実際どんな場面で使われるのか

大規模に SQL 的にデータ解析ができたとして、実際にどんな場面で使われるの? というのが次に気になるところでしょう。

ソーシャルゲームをはじめとする最近のWebサービスではログ解析が重要な役割を占める・・・という話は聞いたことがある人も多いと思います。TD のようなソリューションが使われるのは、まさにそこです。最近は広告なんかも技術革新が進んでかなり大規模なデータを処理するようになってきていて、そこでも使われている。中の人のプレゼン にある事例だとクックパッド、MobFox なんかが有名どころです。資料には載ってないけど、割と国内のソーシャルゲームデベロッパー各社ではかなり導入が進んでいると聞いてます。

そもそも何でそんなことになっているの? という点について少し捕捉しておきたい。

もともとウェブシステムのデータ解析といったらもっぱらそれはウェブサーバーのアクセスログのことだった。Apacheaccess_log、あれ。アクセスログに関しては、最近はログから PV や UU を計算するくらいだったら Google Analytics なんかを最初から使ってる、という事例のほうが多いかもしれない。いずれにしても本質的にはHTTPリクエストから得られる情報だけで分析しているということで得られる情報は一緒です。

このアクセスログ分析では、どのURLにどの程度のアクセスがあったかとか、だいたい日や月にどれくらいの UU があったかといったことはわかる。でも、それ以上はわからない。アクセスしたユーザーの性別や年齢といった個別の属性、トランザクションID、購入しようとした商品・・・みたいなウェブサーバーが感知しようのないデータは含まれていないので、それ以上のことを調べようと思っても調べようがない。

「詳細なデータが取れないなら取れるようにすればいいじゃない」ということで、アプリケーションのロジックから色々とその辺を紐づけたログを吐くようにしてやればいい・・・みんな当然そうするわけです。

どういうコードで例を書いたらいいかちょっと微妙だけども

# 商品購入画面
post '/purchase'  => sub {
    my $self = shift;
    my $item = My::Item->find(…);
    my $user = My::User->purchase( $item );
    
    # インタラクションログを出力する
    $self->logger->emit(
        user_hash => $user->hash,
        age => $user->age,
        sex => $user->sex,
        session => $user->session_id,
        item => $item->id,
        …   
    );
    
    $self->render;
};

こんな感じで、とあるイベントに対してアクセスログだけでは捕捉しようがないデータをログとして書き出してやる。この手のログをあちこちでとっておいて後から解析すれば、例えば「商品購買前の画面で何%がドロップしているけどそれがどんな属性のユーザーだった」とか「一ヶ月に数回以上訪れるユーザーとそうでないユーザーのコンバージョンの程度がこのぐらい違った」なんていう分析が可能になる。このデータを使って意志決定をすれば、やみくもにサイトを改善するよりはずっと確度の高い施策を打つことができるし、A/B テストなんかでの評価にも利用しやすい。

・・・解析できるようになるのはいいんだけど、そんなにうまい話はない。当然いろいろ悩ましい問題がでてくる。特にサイトの規模が大きくなればなるほど。

  • そのログってどうやって収集するの?
  • そんなでかいデータどこにストアするの?
  • そんなでかいデータどうやって計算するの?
  • ログのフォーマット変更にどう対応するの?
  • 計算結果はどうやって参照するの?

ローカルに吐き出したログは、どうにかして解析用のストレージに集めてこないといけない。イベントログという性格上、それはなるべくリアルタイムで収集しておきたい。集めたデータを保存するとして、日に数百GBになるようなデータをいったいどこに保存しつづけるというのか。MySQL? MongoDB? うーん。集めたはいいけど、データがでかすぎて集計のバッチが一日で終わらない・・・!! 計算できるのはいいけど、毎回エンジニアにお願いしないといけない、でもエンジニアが忙しくてやってくれない! ログに新しい属性を追加したい! え、なにあんな巨大な MySQL のテーブルを alter table するわけ? ハードディスクが壊れました! ネットワーク帯域が溢れました・・・!

「ぎゃー」

なーんてことが起こって、まあなかなか、そんなに高度な分析がしたいわけじゃなかったとしても、それなりにここのシステム構築と運用維持は骨の折れる話・・・だった。だからみんなアクセスログ程度の分析で妥協していた。ところが、そこのところを頑張ってきちんとやって、データ分析をもとにした意志決定を可能にしたのが Zynga なんかが有名にし今では一般的になりつつあるかの手法です。

Webサービスのようなスタート小規模B2Cで始まるような世界では、このデータ解析周りというのはここ数年の間に急激に盛り上がった分野だけれども、エンタープライズシステムでは (自分もあんまりよくわかってないけど) ERM やら SCM やらその辺の基幹統合システムから集めた大量のデータを格納し、分析、表示する一連のシステムは DWH (データウェアハウス) と言われて、それはそれはいろんなエンタープライジーなハードやソフトによって実現されてきた・・・らしい。

先日も、とあるエンタープライズな基幹業務に携わっている友人が「基幹のバッチを一日で終わらせないといけないんだけど、データが多すぎて終わらなくって大変。そのために結構な性能の商用製品を買ってる。そのうち Hadoop とか分散システムでやれるといいんだけどね」と言ってました。

ビッグデータの活用は、3つの段階に分けられると考えています。第1段階はウェブログデータが対象で、主にドットコム企業がこれらのデータを解析していました。特に、トランザクションデータの部分に焦点を当てていたのです。しかしビッグデータの到来によって、トランザクションよりもう一段階詳細なレベルであるインタラクションデータ、つまり、やり取りされるデータの中身が解析されるようになりました。

第2段階は、解析の対象がソーシャルメディアに移ってきました。FacebookTwitter、ブログなどに書かれるテキストを対象としたものです。現在はこの第2段階にあります。

と、この DWH 企業の Teradata の CTO が言うようにただのアクセスデータから一歩進んで「インタラクションデータ」を分析・活用するようになったというのが大きな流れでその背後にはビッグデータ(にまつわるハードウェアの進化やソフトウェア技術の登場)があった、というのが近年です。

それを、一部の開発力のある企業は自社のエンジニアががんばったり、あるいは資金力のある企業は専業ベンダーと組んでそいういったものを構築してきたのだけど、AWS が仮想化技術をはじめとして大規模インフラをコモディティ化したように、データ解析システムをクラウドによってコモディティ化しようとする試みる人たちがここ最近でてきた。Treasure Data 社はそんな野心溢れるベンチャー企業のひとつ、なんでしょう。

Treasure Data のアーキテクチャ (ざっくり)

より具体的に Treasure Data は先ほどの大規模ログ解析にまつわる各種問題にどう対応するのか。

この辺は 先日の JAWS DAYS 2013 での @repeatedly のプレゼンが詳しい。

http://cdn.bloghackers.net/images/20130322_184841.png

ログの収集は、Treasure Data がスポンサーになって開発されている OSS の Fluentd で行う。より正確にはその OSS の Fluentd を、Treasure Data 向けに使う前提にパッケージングした td-agent (https://github.com/treasure-data/td-agent) を使う。API キーを入力してちょちょいと入出力の設定をしてやるだけで TD にデータを送ることができるようになっている。Fluentd そのものは非常にスケーラブルな作りになっているし、実績面も(よく知られているように) LINE のバックエンドなんかにも使われていたりして十分。プラガブルなアーキテクチャによってログそのほかの入力を多種多様なフォーマットに対応し、それを JSON という変化に強い柔軟な形に変換して取り扱う。プログラム内から Fluentd にログを飛ばすためのロガーライブラリも、各種言語に対応した実装が用意されている。

データストアは TD 社が独自に開発したカラムナーストレージが使われる。独自に開発したといっても実際には S3 上に構築されたソフトウェアのようで、99.999999999% の堅牢性と 99.99% の可用性を謳う S3 の上に、HDFS の弱点を克服するため(+ そのほか幾つかの目的のため)カラムナー形式のインタフェースを実現したものになっている。S3 なので増え続けるデータに対してスケーラブルだし、カラムナー形式なので特定のデータだけを処理したい、なんてときに余計な I/O が発生しない作りになっているので効率的。

大規模データに対してスケールするための計算基盤は Hive + Hadoop。で、Hadoop を先のカラムナーストレージに対応させている。

計算結果の受け取り方・・・ここは TD のウリの一つでもあって、Web APIMySQL や S3 などいろんな形式で受け取れるようになっている。それらと自社のグラフ化ツール・・・この分野では BI (Business Intelligence) なんて言ったりするけども、そこに流し込んでやることで TD で計算した各種指標を定点観測したりすることなんかもできる。

・・・というデータ収集から出力までの一連のシステムを構築することで「デベロッパーの苦痛」を肩代わりして、またそれをオールインワン、クラウドサービスとしてで提供することによって件の問題を解決している。

Treasure Data vs ...

Bigdata as a Service の流れは何も Treasure Data だけが進めている分野というわけではなく、他にもいろんな競合がいる。特に比較されやすいのは TD のバックエンドにもなっている Amazon が、AWSの一環として提供するデータ解析用の各種サービス。*1 より具体的には

あたりがそれに相当する。
EMR はその名の通り AWS における MapReduce のサービスで、Hive を使うオプションもある。S3 にストアしたデータを読み込んで任意の MapReduce 処理を実行させることができる。Redshift にいたってはまさに DWH そのものです。

それに対して Treasure Data が提供するものはいったい? それも先のプレゼンをみるといい。動画の最後では、まさにそれその通りの質疑応答があったりする。

それに対する答えは、普通に EMR や Redshift を使うだけなら同じだけれど、実際には Treasure Data は収集から出力までを統合的にまとめて面倒を見ていること、そこに豊富な API を用意することでデベロッパーフレンドリーに仕上げていることが大きな差別化ポイントになっている。誤解を恐れずに言ってみれば、生の AWS に対する Heroku、みたいなものだと見てもいいかもしれない。DWH は運用がとにかく面倒なのを我々が面倒見るぜ! というのがこの手のソリューションのスタンスだし、その顧客がいちばんやって欲しい部分に特にフォーカスすることで差別化しているという意味で Treasure Data の戦略は結構筋がいい・・・と自分も思うし方々でもそう見られているようだ。

TD の使用感

実際 TD が解決するのは大規模ログ解析なわけだけれども、自分のように小規模に使うというのでも全く問題ない。というか TD はそれも想定している。

この辺は http://d.hatena.ne.jp/naoya/20130219/1361262854 でも書いた通り今後もずっと増え続けるログをただただ TD に送り続けるだけで良いとう使い勝手の良さ。そのマネジメントをしなくてという精神的安心が得られる。先のも述べた通り、デベロッパーフレンドリーであることをウリにしていることもあって、煩雑な設定もいらないし、凝ったことをしようと思ったらだいたいやりたいことに相当する API が用意されている。その API も Restful でシンプルなアーキテクチャになってて学習コストは低い。

なお、自分は Fluentd を使って出力を2方向にコピーして、生ログは保存目的で S3 に直接転送して、分析向けのいろんなデータをくっつけたものを TD に送りつけるなどして使っています。

どんな風にみえているか

Treasure Data のいまや今後がどんな風に見えるかというのは、携わるシステム大小の視点によって変わってくると思う。

エンタープライズな人や大規模Web屋にとっては既存のDWHあるいは自社で開発したログ解析システムを置き換えるもの、つまり Treasure Data が想定するユーザー像の通りにそれを認識すると思います。実際、クックパッド社なんかは自分たちで Hadoop を運用していたけれどもその運用コストが高くつく、というので Treasure Data に移行したというし、エンタープライズ領域に関しては先に述べた通りバッチに使われる大規模データベースなんかが必要だった部分の置換を想像するところだと思う。「エンタープライズ領域はデータをクラウドに預けられるか問題」といういつもの課題があるのでなかなかスムーズに浸透していかないとは思うが、先進的なユーザーはすでに導入を開始しているということもあって、案外楽観的な未来が待っているかもしれない。

一方、これは個人的な妄想でもあるのだけど、スタートアップや小規模なデベロッパーからは AWS が個人に対しても仮想化サーバーやロードバランサーそのほかを組み合わせたシステムをコモディティ化したように見えたのと同じで、TD社あるいは同社の競合が、これから先データ解析基盤 (DWH) をコモディティ化していくことを期待したい。クラウドはある意味、個人やスタートアップのような小規模なチームをエンパワーメントするツールでもあり、わずか 4人の会社で 1,000 万ユーザーをさばききった Instagram の成功なんかは AWS がそういうサービスなんだということを世の中に知らしめた。TD も同じように、巨人と戦おうとするそんな小さなチームの新しい武器になればいいし、そうなったら楽しい。

・・・というわけでなんか色々書いてたら熱くなってしまって書きすぎましたが Treasure Data の紹介でした。

自分がなんでこんなに Treasure Data 推しかというと、まあ正直に言って CTO の @kzk_mover を知っているから応援したいという個人的な気持ちが結構あるのは隠さない。でも、実際に自分で使ってみたら見事に自分の抱えていた問題を解決してくれたし、技術的も真っ当で、なによりその個人的展望みたいなのを実現してくれる可能性がありそうだから、ついつい期待しちゃったんである。

この記事が結構読まれてさらに将来 TD 社がもっと大きくなってサクセス (!) した日には、特上寿司でも奢ってもらうことにするということで本稿を締めたいと思います。

*1:若干書き方が紛らわしいですがTDがEMRやRedshiftをバックエンドにしているわけではないです。TDはAWSのうちS3、ERB、EC2、RDS程度のみ利用しているとのこと