「勉強会に行ってみた!」第26回「東京ruby会議」前編
event

「勉強会に行ってみた!」
第26回「東京ruby会議」前編

2016.06.16

東京Ruby会議は日本発のscript言語Rubyのプログラム実装技術について議論するカンファレンス。"技術的好奇心を改めて呼び起こし、プログラミングの難しさ、そして楽しさを再発見する場を目指します。”という目的をもったカンファレンスです。今回で11回目となる東京Ruby会議は秋葉原コンベンションホール2Fで行われました。 多くのギークが集まる中で、どんな講演や議論がなされていたのかレポートします。

(鯉渕 哲也)

会場の入り口近辺では技術書やスポンサー企業の展示があり、講演開始前から多くの人で賑わっていました。5Fには休憩室があり、そこでは会場のライブ中継もされていました。仕事をしながら講演を聞く人たちには非常に良い環境でしたね。またチャイルドケアフロアもあり、子供連れや女性にも優しい環境を整えられておりました。

いろいろな本が展示されていますが、 残念ながら販売用ではなく閲覧用です。

休憩室もすごく広いです!! 電源完備なので、ここで仕事をしながら講演を聞く人もたくさんいましたよ!

さて、講演が行われる本会場ですが、さすがは東京Ruby会議! すごく立派な会場です!
今回は、全部で11講演が行われました。どれも素晴らしいお話でしたが、その中で非常に興味深かった講演をご紹介します。

■OSいらずで動く最軽量Ruby「mruby/c」

組込み型の軽量Rubyとしてはmrubyが有名ですが、それよりもさらに軽量な組込みruby「mruby/c」の開発を行っている田中和明氏。開発中のmruby/cの特徴を紹介していただきました。
mruby/cは64KBのSRAM、256KB Flash搭載のマシンで動きます。容量も40KBほどです。VMにOSのような機能を盛り込んでいるので、OSを搭載していないマシンでも動作可能です。プログラムの流し込みはUSB接続で行い、専用ドライバも必要ないそうです。
すぐにでも開発を始められる手軽さですね。
これなら秋葉原でちょっとマイコンを買ってきて、githubからmruby/cのソースを取得するだけで、さくっと試すことができそうです。
デモではmruby/cを使用したLチカを披露。消費電力もmrubyの1/10程度と非常に省エネです。

構造としてmruby/cはGCの機能を備えていません。プログラムを実行したらメモリを初期化します。それはmruby/cが小さなプログラムの実行を想定しているからとのこと。すごくシンプルな仕組みです。
正直、GCがないという点は私としては驚きでした。私たちは非常に優秀な動作環境のおかげで、普段はGCを意識することがなくなりました。まして、メモリ領域に制限がある組込みだからこそ、すごく優秀なGCの構造をしているのだろうなと思っていましたが、これだけ制限がある環境だと、GCはそれ自体がリソースを使ってしまうわけですね。
mruby/cはOS上で動作しないため、マルチタスクではなくVMが複数のプログラムをdispatchして並列処理(交互に実行)を可能にしています。プログラムAとプログラムBがあった場合、それらは別々のworkingメモリに展開され、交互に少しずつ処理されていきます。また、共有メモリ領域もあり、そこにはグローバル変数やクラスメソッドが格納され、複数プログラムで共有されます。

プログラムAとプログラムBを同期処理させたい場合は以下のように記述します。

$lockの値はプログラムA、プログラムBで共有され、プログラムAの後にプログラムBを実行することを可能にしているわけですね。プログラムAとプログラムBで同期処理を実現したい場合には、こういった手法になるようです。ただし、排他制御は意識しなければならないとのこと。こういったところも、プログラマがきちんと考えてコードを書かねばなりませんね。
デバイスを操作してすぐに起動しないとストレスになりますよね。そのため、mruby/cは起動速度を重視しているそうです。通常のRubyの起動時はVM初期化後にclassの生成と全てのメソッドをメモリ領域に展開するわけですが、mruby/cはメモリ上のメソッドのエントリーポイントだけを集めて起動するため、起動は非常に早いです。もちろんメソッドを呼ぶためにはloadしなければならないため、メソッドを大量に呼んだ場合の動作は遅くなります。
下記の図はRuby、mruby、mruby/cの起動と処理速度を比べたものです。

カジュアルにIoTを実現するために、非常に考え抜かれた仕様だなと感服しました。

mruby/cは、まだまだ発展途上とのことですが、IoTプログラミング言語の選択肢が、CだったりPythonだったりが多いので、この中にRubyが入ってきてくれると個人的に非常に嬉しいなと思います。

mruby/cは以下のgithubで公開されています。
https://github.com/mrubyc/mrubyc
田中氏の発表はこちらで公開されております。
https://www.youtube.com/watch?v=Opq50qdiaYE&feature=youtu.be

■分散ワークフローエンジン「Digdag」

ワークフローオートメーションとは、手作業を自動化すること。古橋氏は今制作しているワークフローエンジン「Digdag」についての発表でした。

Digdagはyamlでタスクを定義できます。Rubyを呼ぶタスクであれば以下のように書くことができます。これは、rubyに限らず他の言語も呼び出すことが可能です。また、yamlにはjavascriptを書くことができます。プログラムに渡すほどではない処理はここでも処理させることができるようですね。
私も、deployやTestの実行をオートメーション化していますが、ほかにも色々とオートメーション化したいことは沢山あります。しかも、それをエンジニアではない人から依頼されることもしばしばですが、Digdagだとエンジニアじゃない人でも書けるかもしれません。

このようにプログラムとワークフロー構造は別に書くことができます。またプログラムとワークフローはお互いにパラメータのやり取りも記述できます。Rubyであれば、Digdag.env.storeでデータを共有することができるようです。Rubyでデータを取得して全体のワークフローで使いまわせるのは非常に便利ですね。

私がRubyでタスクを作っておいて、非エンジニアの方がyamlを作れば、私に依頼しなくてもオートメーション化が作れてしまうわけですよ!

Digdagのアーキテクチャはタスクを分解して、workflowExecutorがキューにどんどんタスクを突っ込んでいきます。それをTaskExecutorが順次実行していく構造です。この構造を聞いていて面白かった話がタスクキューのところです。

Digdagでは、キューの構造を実現するためにpostgreSQLを使用しています。RDBでキュー構造を実装しようとすると、ロックの問題で性能が発揮されません。私の場合だと、MySQLでキュー構造を実現しようとしたときには、奥一穂氏の開発した「Q4M」を使用していましたが、postgreSQLを選択肢として考えたことはありませんでした。古橋氏が言うには、postgreSQLを採用した理由はバージョンが9.5以上だと、”with recursive”と”for update skip locked"というSQLが使用可能だからだそうです。

“with recursive”は、ロックされていないデータをid基準に昇順ソートして一つ取得します。indexの張り方次第では相当性能が出るそうです。

"for update skip locked”は通常の”select for update”がロックしているデータを無視してscanしてくれるので、マルチスレッドで実行しても速度が出るとのこと。なるほど。“with recursive”も”for update skip locked”もロックを無視してscanしてくれるので性能が発揮されるんですねー。これは知らなかったので、とても勉強になりました。
Digdagは現在まだ開発中ですが、yamlも直感的でわかりやすいですし柔軟性もあるので使えるようになるのが楽しみです。

古橋氏の発表はこちらで公開されております。
https://www.youtube.com/watch?v=OAaFr_CnXvk&feature=youtu.be

■最速ウェブサーバーの作り方

Digdagの記事でも触れた「Q4M」の開発者であり、また、H2Oというwebサーバーの開発者でもあるDeNAの奥一穂氏。本講演でも大人気の講演でした。
今回は、最速ウェブサーバーの作り方と称して、HTTPの理論上のレイテンシーに近づけるテクニックをご紹介いただきました。

http1.1では、1リクエストに対して1レスポンスしか返せません。取得するリソースの優先度をハンドリングする仕組みがないためです。リクエストやレンスポンスヘッダーが大きいなどの問題がありました。HTTP/2でレイテンシーは早くなったが最速かといえばそうではありませんね。ポイントはどれだけRTTを減らせるかにあり、現状のHTTP/2では一般的なWEBサイト表示で6RTTも通信が発生している状態だそうです。

これを最適化する手法が2つあるそうです。

応答性を優先のTCPプログラミング
理想はブラウザがHTMLを解析して、css,javascriptのリクエストを送信。サーバーがリクエストを受け取った時点でHTMLの送信を止めて、css,javascriptを送ることです。しかし、現状のwebサーバーでは、これを簡単に実装することはできません。webサーバーにはTCP send bufferというカーネルの中にあるTCPで送ってよいデータを格納する領域があります。このTCP send bufferの中にはすぐに送信するCWNDと、次に送るデータをストックするpoll thresholdが存在します。
ブラウザからリクエストを受け付けてレスポンスを返すためには、ここに送信データが格納されるわけです。データは次々に書き込まれ、CWNDに格納できないデータはpoll thresholdに溜まっていくわけですね。そのため、webサーバーがブラウザからcss, javascriptのリクエストを受けて、cssやjavascriptを送ろうとしてもpollthresholdに既に大量のデータが積まれているので、どうしてもすぐにはcss,javascriptの情報が送れないわけです。

そこで、CWNDまでの書き込みを許可するようにして、poll thresholdにデータを滞留させないようにすれば、css,javascriptのリクエストを受け取った時点で、TCP send bufferにjavascriptやcssのデータを格納することができるようになります。理想形は以下のスライドのような状態です。

ただ、これ自体にも問題はあって、あまりTCP send bufferを小さくすると、カーネルとソケットとの間の通信が頻発しシステムコールが増加してしまうので、性能が劣化する可能性があります。また、webサーバーcss,javascriptのリクエストを受けて送信データを用意するまで、TCPsendbufferが空になるので、送信時間を無駄にする可能性もあります。奥一穂氏によると、RTTが大きく、かつ、CWNDが小さい場合のみ適応させるのが良いとのことでした。
奥一穂氏がこの実装をして、アイルランドにサーバーを立てて、日本からアクセスした場合に511msのレスポンスタイムが250msまで改善したそうです。確かに、こうすることでレイテンシーを短縮することができますね。ですが、上記にも書いたとおり、デメリットもありますので、自分で試してみて実装するのが良いと思います。最近ではnode.jsで手軽にwebサーバーを作ることができるので、私も試してみようかなと思います。

キャッシュサーバープッシュ cache aware server push
サーバープッシュとはクライアントからリクエストを受ける前に必要なassetsを返す仕組みです。しかも、ブラウザキャッシュされているassetsを送るのはムダなので、キャッシュされていないものをサーバーで検知して、新規のassetsだけを送る必要があります。

H20の1.5から実装されている機能では、ブラウザキャッシュのURLを集めてダイジェストを作成し、サーバーに送信します。そのダイジェストをサーバーでチェックして送るassetsを決める機能が実装されているそうです。ブラウザキャッシュにはassetsに更新があったかどうかをサーバーに問い合わせないfreshなキャッシュと、更新確認をサーバーに問い合わせるstaleキャッシュがあります。現在H20はfreshキャッシュのみダイジェスト機能に適応しているとのこと。このキャッシュダイジェストをサーバーに伝える手段としては現状以下の3つが考えられるそうです。

1. cookie
2. serviceWorker
3. HTTP/2 frame

3の”HTTP/2 frame"はブラウザベンダー頼みなので、試したい人は、cookieやserviceWorkerを使う選択肢があるそうです。やり方としては、httpヘッダーの中に、Linkタグを書いておくと、H2OやApacheがそこに書いてあるファイルを返してくれるのだそうです。nginxも近々実装するのではないかと言われているそうです。

私も、webアプリケーションを実装していて、ここまでレイテンシーを意識することはなかったですね。当たり前のようにHTMLを表示させて、そこからassetsを取得する通信が発生するのはもうしょうがないと思っていましたが、一穂氏のお話を聞いて、色々やれることはあるなと考えさせられました。現在の開発はフレームワークやデザインパターンが充実していますが、仕組みを理解してさらに良い仕組みが出来ないかと考えることは大事ですね。

奥一穂氏の発表はこちらで公開されております。
https://www.youtube.com/watch?v=Iu5Uynq7ubo&feature=youtu.be

前編は、将来的に期待大のプロダクトや、勉強になったお話を中心に紹介しました。
後編は、rubyを使った興味深い取り組みや、プログラミング言語開発を通して、プログラミングを楽しむという本質を教えてくれた ユニークな講演をご紹介します。

原稿:鯉渕 哲也
株式会社DeNAでゲーム開発&mobageプラットフォーム開発を担当。2015年7月、フリーランスのエンジニアとして独立。現在は、さまざまな会社と関わりながらサービスの開発を行う。得意分野はRubyによるバックエンドシステムの開発。

http://dosukoikoi.com/

この記事はどうでしたか?

おすすめの記事

キャリアを考える

BACK TO TOP ∧

FOLLOW