Feedforce Developer Blog

フィードフォース開発者ブログ

10 分でわかる Ruby Guild

どうも、バックエンドエンジニアのサトウリョウスケです ✌︎('ω')✌︎

RubyKaigi 2018 から早 3 週間。この記事を読んでいる方でも参加された方が沢山いるのではないかと思います。 個人的な感想ですが、今年は例年以上に充実していたんじゃないかな、と大満足です✨

感想記事はこちらの記事に詳しくまとめられています。

developer.feedforce.jp

さて、今回の RubyKaigi の発表では笹田さんから Guild の進捗についての発表がありました。

Guild Prototype

この Guild の概要について社内のメンバーに解説したところ中々に好評だったので、今回の記事では Guild とはどういうものなのかを超ざっくりですがご紹介します。

そもそも論。なぜ Guild が必要なのか?

ご存知の方も多いかと思いますが、現在の Ruby のスレッド処理はマルチコアに対応していません。 最近の PC の殆どにはマルチコア CPU が搭載されていると思いますが、1つの Ruby プロセスが利用できるコアは1つだけです。つまり、並列処理と言っても複数の処理を時間分割して実行しているだけという事になります。 Guild は Ruby でマルチコアを使った並列処理を実現するために必要な機能となります。

ちなみに Guild という名称はあくまでコードネームであるため、リリース時には別の名称になると思われます。

Guild と Thread の関係

f:id:ryz310:20180621191002p:plain

上図のように Guild に Thread が内包される関係になり、プロセス全体でいうと RubyVM → Guild → Thread → Fiber という関係になります。 これを踏まえて、 Guild 導入の前後を図に起こすと以下のようになります(雑な図で恐縮です。。🙇)

f:id:ryz310:20180621183710j:plain

同一 Guild 内の Thread は従来どおりシングルコアで動作します。しかし、 Guild を複数定義することで、それぞれの Guild に所属する Thread は並列に動作するようになります。 Guild が実装されていない現在の Ruby は RubyVM → Thread → Fiber という関係になりますが、言い換えればこれは単一の Guild で作られた Ruby プログラムとみなせると思います。 このことから、Guild が実装されても後方互換性は保たれるのではないか予想されます。

Guild 間のデータの受け渡し

Guild 間でのデータ受け渡しについて、 Shareable Object と Non-Shareable Object という概念が出てきます。 詳細は 発表スライド を見てもらうとして、大雑把に両者の違いを説明すると以下のようになります。

  • Shareable Object
    • Guild 間でデータ共有が可能なオブジェクト
    • 基本的に値が変化しない Immutable なデータがこれに該当する
      • Const や Freeze したデータのこと
      • ただし Array や Hash は Freeze しても内側のデータまで Freeze されないので、 Shareable とはならないので注意
        • これについては Deep Freeze を実装するかも、とのこと。
    • 他にも Isolated Proc という、ブロックの外側の変数へのアクセスを禁止した Proc もこれに該当しますが、詳細は割愛
  • Non-Shareable Object
    • Guild 間でデータ共有が禁止されているオブジェクト
      • データの受け渡しができない訳ではない(詳しくは後述)
    • 主に一般的な変数のこと
    • 単一の Guild にのみ所属する

Shareable Object は Immutable (値が変化しない)オブジェクトなので、並列処理中にデータを共有しても問題ないことはイメージしやすいかと思います。 重要なのは Non-Shareable Object の受け渡しで、以下に示す 2 つの方法があります。

  • COPY
    • データを Guild 間で共有するのではなく、別の Guild にコピーして渡す
  • MOVE
    • 別の Guild にデータを渡すと、元の Guild からは見えなくなる

COPY は参照渡しではなく実体渡しなので、1つのデータに対して同時アクセスすることにはならず、 Thread-Safe なやりとりになります。 一方の MOVE は、データを別の Guild に渡すと元の Guild からはアクセスできなくなる、カットアンドペーストのような振る舞いになります。 こちらも同時アクセスが発生しないため、 Thread-Safe なやりとりになります。

ちなみに MOVE より COPY が利用されるケースが多いだろうとのことでした。

おわりに

RubyKaigi 2018 で発表された Guild について超ざっくりと説明してみました。間違ってるところがあればご指摘頂けますと幸いです🙏 なお、開発中の仕様なので実装までにいくつかの変更があるかもしれません。

想像ですが、 Sidekiq とか Puma のような Thread ベースのサービスは Guild が導入されたら劇的にパフォーンスが良くなるかもしれませんね。 これからの Ruby の可能性に期待が高まります✨