Ruby3x3

我々のテーマは「Ruby3x3」といって、だいたい2年後ぐらいの登場を期待されている「Ruby3」というバージョンを開発中なんですけど、そのバージョンではRuby2.0と比較して、さまざまな各種ベンチマークで3倍のスピードを出すことをやってみようと、高いチャレンジを持ってやっています。3倍速くするんですね。

でも、言うのは易しいんですが、実現はなかなか難しい。さまざまなボトルネックが存在していて、それらを解消するためにさまざまな努力をしています。

具体的に言うと、Rubyのプログラムが遅いと言われたときに、1つの理由だけで遅いことは滅多にありません。

あるアプリケーションはCPUをたくさん使いすぎていて、CPUのパフォーマンス、CPUの性能そのものがボトルネックになっている。あるいは、メモリがボトルネックになっているアプリケーションも意外と多い。それから、I/Oがボトルネックになっているものもあります。それぞれのボトルネックに対して、個別に違う対処法が必要になってきます。

例えばCPUがボトルネックになっている場合は、そのVMの性能が問題になっている。つまり、ネイティブコードにコンパイルされたものに比べて、バーチャルマシンで実行するものはだいたい抽象化のレイヤーが1段上がっているので、抽象化のレイヤーを1枚かぶせるために、概算でいうと10〜100倍遅くなるんですね。

そうすると、もしRubyのプログラムをネイティブコードにコンパイルできれば、うまくすると今のバーチャルマシンを介した実行より10倍速くなる可能性があるわけです

そこで、今はRubyのプログラムをバーチャルマシンのコードに変換して実行しているんですが、それをさらに実行時にネイティブコードに変換すれば、もしかすると10倍とか速くできるかもしれない。そういう余地がある。

実際に、JITコンパイラ、Just-In-Timeコンパイラということで、実行時にRubyのプログラムをコンパイルするものを開発中です。12月25日にRuby2.6というバージョンをリリースする予定があって、今日が14日なのであと10日ほどでリリースされるんですけど、そのバージョンには、最初のバージョンのJITコンパイラが使われます。

ある種のCPUがボトルネックになっているベンチマークでは、3倍近くの高速化が観測されています。ただ、CPUがボトルネックになっていないソフトウェアはまったく速くならないので、そこは気をつけないといけない。魔法のようになんでも3倍速くなるといんですけれども、現実はなかなか甘くないですね。

Rubyを使う世界のサービスたち

Rubyで大きなサービスを提供している会社はたくさんあります。Airbnbもそうですし、それからクックパッドさんも。

あるいは、中国。中国は日本よりさらに人間が多いので、中国でサービスを始めるとトラフィックが日本以上にあっという間に集まる傾向があるんですけど、中国のエンジニアの人たちと話をしてると、実はさっき言っていたJITコンパイラに対して、そこまで過大な期待を持っていないんですね。つまり、日々の分析の中で、ボトルネックはメモリにあると考えている人が意外と多い。

実際、Rubyを動かしているときに、メモリがボトルネックになっていて使えなかったり、あるいはより多くのサーバが必要になるケースはかなり多い。

そこで、Ruby2.0のリリース以来、例えばメモリ管理の部分、例えばGCとか、そのデータ構造の持ち方とか、そのへんをずいぶん改善しています。なので、メモリ消費量についても日々改善を行っています。

さらに、I/Oがボトルネックになっているもの。とくにWebアプリケーションはネットワークを通じて、リクエストを受け付けてレスポンスを返しますし、それから多くの場合はクラウドというかデータベースにアクセスしにいくんですね。そうすると、ネットワークのアクセスはコンピュータそのものと比べるとものすごく遅い。

コンピュータが、例えばメモリにアクセスする、あるいはキャッシュにアクセスしにいくときに比べて、ネットワークへのアクセスは、まずシステムコールを呼んで、カーネル空間の中でネットワークドライバーが動いて、ネットワークドライバーがケーブルを通じて次のルーターにつながって、そのあとリレー方式で海の向こうのマシンまでつながる。こういう操作は、実際にメモリにアクセスするときに比べて、何万倍、何十万倍あるいは何百万倍も遅いんですね。

そうすると、CPUのところでいくらがんばって速く動かしても、じゃあちょっと通信といった瞬間に、百万倍待たなきゃいけないことになる。そういうケースがかなり多いんですよ。

そういうケースに対しては、正直いうと、あんまり万能の方法はないんですけど、プログラムがI/Oで待つ時間をどれだけ減らすかということが関わってきます。

幸い、現代のコンピュータはたくさんコアがある。例えばデュアルコア・クアッドコア・オクタコアとか、1つのCPUチップの上に8つあるいは4つとか、そういうCPUを積んでいることが多いんですね。それらのCPUを使ってできるだけ待ちを減らすことで、性能を改善する方法があります。

並列実行をいかに改善するか?

Ruby3では、そうやってマルチコアを改善するために「並列実行をいかに改善するか?」ということも大きなテーマになっています。

パフォーマンスの改善以外にも、エラーをいかに発見するかによって、ソフトウェアのコードのスケーラビリティ、ソフトウェアが複雑になったときにいかに対応するかも、大きなテーマになってきています。

Ruby3では、言語そのものは変えたくないんです。ほかの言語みたいに、例えば「型宣言を追加します」ということはしたくない。RubyはRubyのままでいてほしいので。言語は変えないで、サポートツールを増やすことによって対応しようと思っています。

例えば、ByeBugというRubyのデバッガーがあるんですけど、そのデバッグ効率を改善するような、下回りになるような機能をバーチャルマシンに追加しようとしています。

あるいは、Rubocopという静的解析ツールがあって、このツールで「あなたのソフトウェアコードの中でこのへんがよくないですよ」「このへんを改善するともっとよくなりますよ」あるいは「コーディングスタンダードに従っていませんよ」みたいなことを、より多くチェックできるようにしたい。そういうツールはすでにあるんですけど、それを改善していく。

あるいは、Standardsというgemを使って、中身はRubocopを使ってるんですが、Rubyのコードフォーマットの、コーディングスタンダードの、コーディングスタイルの揺れを減らしたりとか、そういうことを標準化できるようにしようと思っています。

あるいはSteep・Sorbet・RDL、それぞれRubyで静的型チェックをするためのツールなんですが、これを統合してRuby3の型チェックを行うツールを提供しようとしています。

あと、コードを解析するために必要なAbstract Syntax Tree、抽象構文木を提供するようなAPIを準備しています。

それらを使って、例えばLanguage Server Protocol、いくつかのエディタやIDEで共通的に言語開発を支援するプロトコルで、Microsoftが提唱しているのですが、このプロトコルに従ったサーバを用意できればと思っています。

このような静的なコード解析を行ってコード開発を支援するツールとか、最終的にはインタラクティブな開発支援を行うようなツールを提供していこうと思っています。

汎用言語としてのポジションを維持していきたい

未来のプログラミングの理想としては、AIとペアプログラミングできるようになればいいんじゃないかと思っているんです。プログラミング業界の冗談として、ペアプログラミングの相手が見つからないときは、隣にテディベアを置いて、そのテディベアと話しながら開発すると開発効率が上がるというものがある。これ、実際に上がるんですね、不思議なことに(笑)。

AIを使って、より賢いテディベアを作れるようなツールを提供できることが理想なのではないかと思っています。そういうことを目指しています。

結局大事なのは、死なないこと。プログラミング言語として死んだと思われないことが大事なんです。もちろんランキングの上下とか「Rubyは死んだ」って言われるとか、そういう些細なことはあるんですけど、ある種の人々にとってRubyが使い物にならない、今まで使えていたのにもう使い物にならなくなったという事態は望ましくないわけです。

そのためには、足を止めない、歩き続けることが非常に重要であると思うんです。さらに、諦めたら試合終了なので「Rubyの改善はもうやめます」「Rubyの進歩はもうやめます」みたいな、諦めることは決してしない。

幸い、今のところ、大きな「スケーラビリティ」というテーマの下に、個別のやるべきこともたくさんある。それらを1つずつ改善していくことで、Rubyという言語を極端に変えないまま、生産効率をどんどん改善する余地がまだまだあると思っています。それを続けようと思います。

Rubyを作り始めてから25年経ちました。最初はスクリプト言語だと思って作ったんですけど、Ruby on Railsなどの登場によって、Webアプリケーションを開発するための言語というところにポジションを得るようになりました。

これから先25年も同じ進歩を続けていって、Web言語だけではなくて、もともと汎用言語ではあるんですけど、名実ともにさまざまな領域で使える、Webでももちろん使えるし、組み込みにも使えるし、システムアドミに使えるし、もちろんスクリプト言語にも使える。あるいは人工知能とかScientific Computingなところにも使えるという、そういう汎用言語としてのポジションを、次の25年でもキープし続けていきたいと思っています。

今後の課題

今後の課題としては、例えばFaaS、Function as a Serviceみたいな領域に出ていきたいと思います。

ついこの間の「re:Invent」、ラスベガスで行われたAmazonのテクニカルカンファレンス、AWS Lambdaでは、正式にRubyが使えるようになるというアナウンスが出ました。今までもちょっとハックを使えばできたんですけど、正式に使えるようになる。

そうすると、その新しいサーバサイドのプログラミング主体である、LambdaみたいなFunction as a Service、MicrosoftだとAzure Functionsでしたっけ? そんな感じのスタイルでもRubyが活躍することを今後も期待したいと思っていますし、あるいは、クラウドのコンフィギュレーションとか、DevOps領域とか、そういうところでもRubyを使っていただきたい。

あるいは、データサイエンスでも機械学習でもRubyが使えるような、さまざまなチャレンジがすでに行われています。だから、AI分野でもRubyは使いものになるようにやりたいと思っています。

あるいは、IoTとかデバイスのプログラミング。mrubyとか、そういうものを経由してRubyを使えるようにしたいという試みをしています。

目指すところとしては、どこでも・いつでもRubyが使えるようにしたい。Rubyは、今までと同じように、あるいはいっそうみなさんの手に馴染む道具として、困ったときにRubyを使えばプログラムできるような道具として存在し続けていきたいと思いますし、また、手に馴染んだ道具で戦える領域を、さらにさらに広げたいと思っています。

それこそが、私たちコアチームがRubyに求めている、Rubyをこういうふうに持っていきたいと思っているところなんですね。

もちろんそのコアチームは、Rubyへの「こんなことができたらもっと適用範囲が広がるのに」「こういうところがあったら今のソフトウェア開発適用できる。ソフトウェア開発の生産効率や柔軟性がもっと高まるのに」というリクエストに対して、技術的に応え続けていくつもりではあります。

そのためにRuby3を作ったり、Ruby3のパフォーマンスを改善するためのさまざまなプロジェクトを実行しているわけなんですが、それだけだと足りないんです。

つまり、「Rubyという言語がすばらしいからRubyがすばらしい」だけではなくて「Rubyをこんな領域に実際に使ってみました」とか「こんな領域で使ったらこういうところが足りないので、ここを直したらもっとよくなります」というアイデアとか。それから「こんなgemを使ったらRubyがもっとよくなりました」というものが今まで積み重なってきたんですが、それをさらに推し進めるような新しいgem、新しい試みがぜひとも必要です。

なので、Rubyを広げるというのは、自分じゃない誰か、あるいはコアチームが広げるだけではなくて、コミュニティ全体としてRubyの適用分野を広げる、あるいはRubyの今の適用分野を深めていくことが必要なんです。

Rubyがビジネスの成功率をあげる存在であるために

「Rubyのコミュニティって誰か?」という話もありますけど、Rubyを使っている一人ひとりが、自分のプログラムを作るときにもう1歩踏み出すことによって、あるいは自分の持っているものをもっとシェアすることによって、Rubyの生産効率とか適用範囲とかが広がっていくのではないかなと思います。

「Ruby biz グランプリ」という賞があって、昨日表彰式を帝国ホテルでやりました。ベンチャー企業が多かったんですけど、さまざまな領域の企業がRubyを使ってビジネスにチャレンジしておられました。

開発効率とかサービスインまでの速さ、あるいは試行錯誤するための回数、あるいはピボットの回数とか、そういうものに対してRubyが助けになったという話をたくさん聞きました。

私自身はRubyを作っているので、Rubyかどうかは非常に重要なんですけど、みなさんにとって、Rubyかどうかはクリティカルではないんですね。

結局、みなさんがなにかソフトウェアを開発して、それで成功することがけっこう大事だと思うんですけど、そのためには、みなさんがリスクを取ってなにかを挑戦するときに、その成功確率を上げるためのツールとして、Rubyというものは非常によいツールではないかなと、自画自讃しているわけです。

足りないところがあれば改善するつもりはありますし、Rubyによってみなさんがより多くの回数挑戦できるように、あるいはRubyを使うことでみなさんのチャレンジがより高い確率で成功するように、支援していければと思っています。それ自体が私たちにとっての技術的チャレンジでありますし、楽しみでもあります。

念のため言っておきますけど、Rubyはフリーソフトウェア、オープンソースソフトウェアなので、みなさんがRubyを使ってビジネス的に大成功しても、私には一銭も入らないんです(笑)。ただ、みなさんが喜んでいる顔が私にとっての報酬ですし、Rubyコミュニティ全体でお金が回ることによって間接的に私にもメリットはあるので、ぜひみなさんに成功していただきたい、儲けていただきたいと思います。

いつもポケットにRubyがあるように。そして、Rubyでもってみなさんが成功するように祈念しております。この講演はRubyアソシエーションの提供でお送りしました。ありがとうございます。

(会場拍手)

JITコンパイラについて

司会者:まつもとさん、ありがとうございました。少しお時間がありますので、もし質問がある方がいらっしゃいましたら手を挙げていただければと思いますが、いかがでしょうか?

質問者:今の話で、危機感を持って常に前へ改善していくことがすばらしいなと思って聞いていました。先ほど、JITコンパイラの話があったと思います。私はどっちかというとRailsで使う側の立場にいます。その場合、例えば2.6が出たときに、なにか作業をしなきゃいけないのか、それとも自動的にJITコンパイラが動いてくれるのか、そのあたりをお聞きしたいです。

まつもと:技術的な話をすると、Rubyインタプリタを「--jit」というオプションをつけて起動すると、JITコンパイラが動きます。なので、例えば環境変数「RUBYOPT」が引数の代わりに使えるので、環境変数「RUBYOPT」の中に「--jit」という文字列を足していただければ、JITコンパイラをオフにした状態でみなさんのアプリケーションを動かしていただくことができます。

ただ、現時点では2つ問題があって。まず、現在のJITコンパイラは、JITコンパイラオフの状態に比べてかなり多くのメモリを消費します。さっきも言いましたけど、Webアプリケーションの多くはメモリがボトルネックになりがちなので、JITコンパイラをオンにした状態だと、ボトルネックに先に到達してしまう可能性があります。これが1つ。

もう1つは、Rails自体がかなり大きなアプリケーション、フレームワークも……全体を入れるとかなり大きなコード量なので、JITコンパイルを行わなきゃいけない領域がかなり広いんですね。正直にいうと、Ruby2.6の状態でJITコンパイラをオンにしてRailsアプリケーションを動かすと、現時点ではアプリケーションは遅くなります(笑)。

さまざまな高速化のアイデアがあるし、まだ実装していないものがたくさんありますので、最終的には、少なくとも遅くはならないようなところまで持っていくつもりではあります。が、少なくとも10日ほど先にリリースされるRuby2.6リリース時点では、JITコンパイラをオンにすると、残念ながらほとんどのRailsアプリケーションは遅くなります。

ただ、動くかどうかという意味でいうと、動くところまで持っていったので、そこは1年前とかの状態に比べると格段の進歩だと思っていただければ。まだ成長途上です。

質問者:じゃあ、それは3.0では改善する予定になっているんですか ?

まつもと:そうですね。3.0では、JITをオンにしただけで3倍(のスピード)というわけにはなかなかいかないと思います。RailsアプリケーションでCPUがボトルネックになっているケースはほとんどないので。ただ、JITコンパイラをオンにしたからといって、パフォーマンスが遅くなることは少なくともないと。

メモリ消費量は増えるけれども、メモリがいっぱいあるケースも当然ありますから。メモリがいっぱいあればJITコンパイラがいても遅くはならないし、CPUが負荷になっている部分についてはだいぶ改善できるところまで持っていきたいと思っています。

質問者:ありがとうございます。

司会者:ありがとうございました。それでは、あらためまして、まつもとさんに拍手をお願いいたします。

まつもと:ありがとうございました。

(会場拍手)