RubyKaigi 2013 レポート

Jose Valim,Rubyにおける並行プログラミングのためのいくつかのアイデアを提案。~ RubyKaigi 2013 基調講演 2日目

この記事を読むのに必要な時間:およそ 4 分

2013年5月30日~6月1日の3日間,お台場にある東京国際交流館にてRubyKaigi 2013が開催されています。基調講演をそれぞれレポートします。

画像

2日目の基調講演の演者はJose Valimです。司会の角谷さんにより「再起動したRubyKaigiの基調講演に最もふさわしい人物の一人」と紹介をされたJoseは,Rubyにおける並行プログラミングの可能性について話しました。

自己紹介

Joseは,2006年からRubyを書き始めたそうです。それからOSSにも深く関わっており,2010年からRails coreチームにジョインしています。そして,Elixirという言語の作者でもあります。ElixirはErlangのVMの上で動作するスクリプト言語で,並行プログラミングと相性が良く,強力なメタプログラミングの機能を持っています。現在のバージョンは0.9.0となっています。 現在はplataformatecに所属しています。

画像

どうして,いま,並行性(concurrency)なのか

Joseはまず,並行性をテーマとした背景を説明しました。

かつて,それぞれのサーバ上のCPUのコアは一つでしたが,いまや数多くのCPUコアを持ったサーバを利用することは非常に現実的な選択となりつつあります。例えば,50コアを持ったサーバが2,600ドルで購入可能な例を説明しました。

そして,かつてはCPUの性能向上に比例してソフトウェアが速くなっていたという事情を説明しました。コア数が1つでCPU自体のクロック数を向上させれば良かった時代には,プログラムの側もそのような「フリーランチ」の恩恵を受けていたとのことでした。ですが,メニーコアが前提となったプログラミングにおいては,プログラム自体をそのようなアーキテクチャに対応させなければいけない,そのような状況は未来のものだと思われていたが,その「未来」はもう来ているのではないか,と話しました。

プログラム自体をそのようなメニーコアに対応させる場合,Rubyの場合はスレッドを利用して実現することになりますが,その中でもいろいろな問題が起こりうることを示しました。

クラスのアクセサにおけるレースコンディション

一つの問題は,スレッドによるレースコンディションです。

単純なクラス変数へのアクセサを経由した代入を考えてみます。例えば,WebアプリケーションのUser.current_userという変数があるとします。

そして,コントローラーで次のような処理をしているとします。

  • User.current_userにユーザをセット …(1)
  • 少し時間のかかる処理を実行する …(2)
  • ユーザにメールを送る …(3)

しかしながら,このような処理を行うと,例えば(1)?(3)がユーザごとに直列で実行されているような場合には問題は無いのですが,いくつかのスレッドを同時に動かしている状況においては,問題のある挙動をしてしまう場合があります。

具体的には,ユーザー「Jose」がアクセスして,その(2)の処理が動いている間に別のユーザー「Matz」がアクセスしてしまうと,current_userが置き換わってしまい,結果的にJoseに送るべきメールがMatzに送られてしまうということが起こりうると説明しました。

画像

このようなUser.current_userは,「共有されていて,変更可能な状態で,グローバル変数のようなものだ」とのことです。

そして実は,そういう風にセットできる値がRailsにはかなりの数存在し,例えばActionMailer::Base.fromActionController::Base.loggerなどがそうだとのことです。実はJose自身のライブラリであるDeviseなどにもそのような設定項目はあります。

様々な実装の存在するRuby - 実装による違い

Joseは,Rubyには様々な実装が存在することを紹介しました。そして,スレッドセーフとは,実装によって意味が様々に変わってくるという主張をしました。

例えば,RailsのActionView::Resolverが内部で行っているように,ある変数にHashオブジェクトを代入し,そのハッシュをキャッシュのように利用することが,Rubyのプログラムではしばしば行われます。

ここで問題があります,では,このHashオブジェクトはスレッドセーフなのでしょうか?

実は,この答えは実装によって変わります。YARVではyes,そしてJRubyやRubinius 2.0ではnoとなります。実はYARVではGVL(Giant VM Lock,OSレベルのスレッドを一つしか走らせないロック)が存在するため,複数スレッドからのハッシュへのアクセスは安全に行われるのです。しかしそのような機構が無いほかの言語では,複数のスレッドからハッシュへのアクセスが発生することが起こり得ます。

画像

そのため,例えばRailsでは,実装の間での差異を吸収するためにthread.rbに定義されているMutexを導入しています。ですが,Joseはそのような方法は個人的にでは古くさい,好きではないと言います。あまりにも低レイヤーの実装を,開発者にさせてしまうことになるからです。

この手の低レイヤーなプログラミングについて,次のように表現しました。

  • コードのメンテナンス性が下がる
  • YARVのパフォーマンスも下がる
  • 開発者の幸福度も下がる!

そこで,適切な,並行プログラミングのためのセマンティクスをRubyに定義することが必要であると述べました。

著者プロフィール

近藤宇智朗(こんどううちお)

業務システム→ECサイト→オンラインゲームな雑食プログラマ。Ruby好き。Sinatra,Padrino,Rackなどが好き。

WEB+DB PRESS誌でも,連載「一歩先行くRuby」(vol.69~現在),特集「コードレビュー実践入門」(vol.72)など,何点か寄稿している。

最近興味があるのは型システムが強力な言語。

twitter : https://twitter.com/udzura
blog : http://blog.udzura.jp

コメント

コメントの記入