RubyKaigi 2023に参加しました & 登壇しました
皆さんRubyKaigi 2023お疲れ様でした! あっという間で本当にたのしい3日間でしたね。わたしは一週間が経ってもいまだにわくわくした気持ちで日々を過ごしています。
今年もありがたいことにDAY2に登壇の機会をいただいたので、この記事では今回作ったものや会期中のあれこれを振り返ってみたいと思います。
今回の発表テーマを選んだきっかけ
今回はImplementing "++" operator, stepping into parse.yというタイトルにて「"MRIにインクリメント演算子を追加する"という取り組みを題材に、MRIの字句解析器(スキャナ)と構文解析器(パーサ)に親しむ」というテーマでプロポーザルを提出しました。
(今年のRubyKaigiはパーサ関連の発表が豊作だったので、思いがけず空前のパーサブームに加わることができて幸運でした)
自分自身の個人的な技術的興味はネットワークの分野にあるのですが、昨年のRubyKaigiに参加して、もう少しMRIの内部実装に対して自分の解像度を上げたいという気持ちが湧いた、というのがパーサに興味を持つことになったきっかけです。
発表の中で一番伝えたかったことは(発表中にうまいこと言えていなかった気がしますが)、プロポーザルのpitchに書きました。
The Ruby parser is very mature and there is an ambitious project underway to rewrite it.
(注: プロポーザルを書いた時点では金子さんの開発されているパーサジェネレータであるLramaの進捗をちゃんと把握していなかったので何かふわっとした表現になっています)
It made me feel as if parsers were out of reach for me.
But on the other hand, the fact that I was able to modify it, even though I am not a parser expert, is worth sharing to spark people's interest in the parser of Ruby. I don’t want Ruby internals to be unfamiliar to the rest of us.
わたしはRubyが好きなので、自分も含めてRubyの内部実装に親しんだり身近に感じられるともっとRubyがたのしくなるのではないかな、と思いこのようなPitchを書きました。
(その点でいうと人々が名著Rubyのしくみを読みたいと思うモチベーションももしかするとこの辺りにあるのかも…と勝手に思っております)
Ruby++開発日誌
とはいってもそもそも自分自身がMRI初心者なので、一体何から始めれば…と思っていたところ、Fukuoka.rbメンバーであるいでさんが前述のRubyのしくみや今回とてもお世話になったRubyソースコード完全解説(あるいはRuby Hacking Guide、RHG)を読まれていたのに触発されこれらの本を読み始めました。
(実はRubyのしくみはすでに読んだことがあったのですが、何度読んでも自分には難しく、今回が4回目か5回目の挑戦になりました。RHGのパーサの章も最終的には4回くらい読みました)
(あとは今回の題材に直接関係はないのですが、RubyでつくるRuby ゼロから学びなおすプログラミング言語入門を読んだり、WEB+DB PRESSで連載されていた「Rubyのウラガワ」を読んだり、Go言語でつくるインタプリタを読んでRubyで実装し直したりしていました)
ところで、前述のRHGの第 8 章「Ruby言語の詳細」「自己代入」の節には以下のような記述があります。
+=があるなら++もあるのかな、と思いきや++はない。なぜだろうか。 Rubyでは代入は言語処理系が扱うものである。一方メソッドはライブラリが実 行するものである。この二つ、即ち変数世界とオブジェクト世界、をきっぱり分けるというのはRubyの重要な特徴である。++を導入するとその区別が 壊れてしまいかねない。というのが++のない理由だ。
(Rubyソースコード完全解説 第 8 章「Ruby言語の詳細」「自己代入」)
つまり、Rubyに++
がないのは言語デザイン上の都合であり、実装上は足そうと思えば足せる状態にある、ということです。
この実装に挑戦してみることで当初の目的であった「MRIの内部実装に対して解像度を上げる」が部分的にであっても実現できるのではないか、と思い立ちました。
(RubyKaigi直前のAsakusa.rb Welcome Drinkupにて中田さんが「構文解析は言語実装の心臓部」と仰っていたので、結果的に切り口としてはなかなか良かったのではないかと思います)
ということで、Rubyにインクリメント演算子を足すために色々試行錯誤した結果がこちらです。
発表資料
発表をお聞きの方にはご存知の通り、上記のリポジトリには4パターンの++
演算子の実装があります。
++
をInteger#succ
で置き換える++
を自前のメソッドで置き換える++
をスキャナで+=1
に置き換える++
をパーサで+=1
に置き換える
発表内でご紹介したのは上記の順通りなのですが、発表後に何人かの方から「実際あの発表順通りに実装したわけではないですよね?」と突っ込みをいただきました。
仰る通りで実際には発表と真逆の順番で実装していったのですが、流れを考えた結果発表上は上記の順にご紹介しました。見透かされていてすごいなあ。
最初の実装
++
を実装する…といっても実際には何をすればよいのかさっぱりわからず、しばらくはparse.yやcompile.cやinsns.defあたりを開いては閉じ、宙を眺めるという無為な日々を送りました。
とりあえず思いついた案を並べると、
- 案1. レシーバを破壊的に変更するようなメソッドで
++
を置き換える - 案2. 字句解析時に
++
を読み込んだら+=1
を再現するような処理を行う - 案3. 新しい記号と構文規則を追加し、構文解析時に
++
を表す記号の並びを得たら+=1
を再現するような処理を行う
これらのいずれかに着手する前に、まずは取っ掛かりとして++
に一番挙動が近そうな+=1
を構文解析する際のMRIの挙動を調べようと思い、+=1
の構文解析ログと照らし合わせてparse.yを読むことに着手しました。
その際金子さんさんからいただいたアドバイスを参考にしたりしながら構文解析ログを一行ずつ読んでいるうち、何かだんだんたのしくなってきてしまい「このたのしさを誰かに伝えたい!」と勢い余って鹿児島Ruby会議02で構文解析ログリーディングのたのしみ方についてお話をするに至りました。
構文解析ログを一行ずつ読みながらスタックの状態を一つ一つ整理することによってスキャナとパーサが協調して動作する様子のイメージがつきやすくなるので、これはとてもよい経験でした。
また、この発表資料は発表前、金子さんとそしてRHGの著者である青木峰郎さんに内容の正誤確認をしていただきました。おかげさまでMRIにおける構文解析の様子をざっくり掴むのに便利な資料ができたのではないかと思います。その節は大変ありがとうございました。
(あと鹿児島Ruby会議02もとてもたのしかったです!)
そんなこんなでparse.yの様子が少しずつ掴めてきたのと、+=1
への理解が深まったところで最初に考えた案を再検討しました。
- 案1. レシーバを破壊的に変更するようなメソッドで
++
を置き換える- そもそも
Integer
はイミュータブルなので無理そう (→この案は後で3つ目の実装に引き継がれました)
- そもそも
- 案2. 字句解析時に
++
を読み込んだら+=1
を再現するような処理を行う- 要は字句解析時に
++
を読み込んだら記号tOP_ASGN
とtINTEGER
を返すということ。しかしスキャナは一度に2つの記号を返せないので無理そう (→この案は後で2つ目の実装に引き継がれました)
- 要は字句解析時に
- 案3. 新しい記号と構文規則を追加し、構文解析時に
++
を表す記号の並びを得たら+=1
を再現するような処理を行う- これは構文解析時に
new_op_assign()
を呼ぶだけなので、右辺(整数1
)の値を用意できさえすれば実現できるかも?
- これは構文解析時に
ということで最初に着手した実装は「案3. 新しい記号と構文規則を追加し、構文解析時に++
を表す記号の並びを得たら+=1
を再現するような処理を行う」でした。
このとき、+=
の右辺となる整数1
の値をどうやって作るかについてはちょっと悩みましたが、
- 整数
1
を字句解析する際に呼ばれる関数set_integer_literal()
が呼ばれてからパーサに記号を返すまでの流れを確認する - そのうち整数
1
のRNodeを作成するため必要そうな処理のみを抜き出す - ↑をアクションの中で実行する
と言う手順でこれを実現することができました。
そうして完成したのが最初の実装です(つまり、本発表における完成版のRuby++です)
裏話として、実は今年は当初30分のフルトークではなくLTの方にプロポーザルを出そうと思っていたため(※1)、当初はここまでの実装で一旦完成、という予定でした。
なのですが、その話を上司のmoroさんにしてみたところ「面白そうなので3つの案のうちなぜその実装を選んだのか、という試行錯誤も含めて30分トークの方に提出してみたら」と提案をいただき、また後日Ruby3.2のリリースパーティの席でも金子さんから「パーサに興味を持つ人は希少なので、LTと言わず30分喋ってください」(※2)とお誘いいただき、それならばとこの題材で30分喋ることができないか考え始めたのでした。
moroさん金子さん、その節はありがとうございました🙏
※1 本編での金子さんのLTがあまりに面白すぎたので、今となっては逆にLTだったら落ちていたかもな、と思っています
※2 金子さんご自身のRubyKaigiでの発表によってパーサに興味を持つ人が急増したっぽいので、結果的にこの言葉はfalseになってしまいましたが…
実装2: ++
をスキャナで+=1
に置き換える
さて一つ目の実装は完成したのですが、上述のRuby3.2のリリースパーティにて金子さんから「別の実装方法もあるのではないか」と示唆されたこともあり、「案2. 字句解析時に++
を読み込んだら+=1
を再現するような処理を行う」について実現できないか再検討してみました。
スキャナで+=1
を再現するにはスキャナから記号tOP_ASGN
とtINTEGER
を両方返す必要があります。
++
という文字の並びを凝視しているうち、ここに+
と+
という二つの文字があることを発見し、前方の+
でtOP_ASGN
、後方の+
でtINTEGER
を返すという方法を閃きました。
ということで出来上がったのがこちらです。
この実装では期待するスキャナの挙動を紙に書き起こしながら案を練りました。
実装中にも思いがけず苦労した点があり、それは当初、スキャナのカーソルの位置に対する自分の認識が間違っていたことによるものです。
/* Structure of Lexer Buffer: lex.pbeg lex.ptok lex.pcur lex.pend | | | | |------------+------------+------------| |<---------->| token */
( ruby/parse.y at master · ruby/ruby · GitHub )
問題になったのはここ、現在のカーソルの位置よりも一つ手前の文字を参照する部分です。
if (peekc_n(p, -2) == '+') { // ... }
ruby-plusplus/parse.y at 6b4f944aeaa5ec5d1c2c57d6e4e972aa519e6a64 · shioimm/ruby-plusplus · GitHub
「一つ手前」なのでpeekc_n(p, -1)
かと思いきや、当初思っていた位置よりも一つ先に進んだ場所にカーソルの読み込み位置があり、peekc_n()
の第2引数に-2
を渡す必要がありました。
同様のことをしたいと思われた方には是非お気をつけください、とお伝えしたいところなのですが、この実装については中田さんから後日「Note that peekc_n
does not consider negative offset.」というコメントをいただいています。素人考えって怖いですね。
(とはいえカーソル位置が実際どこなのかについて注意が必要、という点は知見なのではないかなと思います)
なお、この実装が実際にうまくいったかどうかについては発表でご紹介した通りです。
実装3: Binding#local_variable_set
でレシーバを置き換える
ここまで2パターンを実装できてしまった(?)ので、「案1. レシーバを破壊的に変更するようなメソッドで++
を置き換える」にも実装可能性を感じ始めてしまいました。
ということで出来上がったのがこちらです。
Integer#__plusplus__
メソッドの実装にあたりイミュータブルなレシーバの値を更新する方法に考えを巡らせていたのですが、今回のプロポーザルおよび後日発表資料の英語レビューをしてくださった大倉さんとお話ししていた際、大倉さんから「これがRubyのレイヤなら変数の値を更新するのにBinding#local_variable_set
を使うんですけどね」とのヒントをいただいてなるほどと膝を打ち、パーサのレイヤでもそれを実現できないか試してみることにしました。
改めまして大倉さん、ありがとうございました!
しかしいざアクションの実装に入ってみると当該環境を表すBinding
オブジェクトを得る方法がなかなかわからず、結果的には最も苦労した実装になりました。
要するに現在の実行コンテキストでself.binding
を呼び出した結果のRNodeが必要なのですが、この時self
を得るためにNEW_SELF()
を呼び出してしまうとそのself
は今実行しているコンテキストとは無関係の野良のself
(つまりmain
)になってしまうためです。
実行コンテキストとself
を紐づけるべくbinding
を呼んだ際の構文解析フローを追ってみたり、他にも思いついたこと目についたものを片っ端から試してみたのですがいずれもうまくいかず、self
とは一体何なのかすっかりわからなくなってしまいました。
「実行時のコンテキスト」とは一体何なのか…selfとは…🫠
— Misaki Shioi (しおい) (@coe401_) 2023年1月23日
万策尽きて一ヶ月ほど呆然としていたのですが、ふとRubyKaigi 2010でのあんどうやすしさんのLT、parse.yの歩き方 -ワシのRubyは4式まであるぞ-を観ていると、同じようにアクションの中でBinding
オブジェクトを取得しており、そのためにあんどうさんはNEW_VCALL()
を使用されているのを発見しました。
そしてこれを試してみたところ、やりたかったことがあっさりと実現できたのでした。なるほど、必要なRNodeはVCALL
でしたか…
ということであんどうさんとは直接面識がないのですが、おかげさまで実装が完成したのでこの場を借りてお礼を申し上げます。本当にありがとうございます。
なお、ここまで頑張って仕上げたこの実装の顛末は発表中でご紹介した通りです。
実装4: ++
でInteger#succ
を呼ぶ
ここまでの実装でプロポーザルを書き(正確に言うとひとつ前の実装はまだ完成していなかったのですが…)、ありがたいことにapproveをいただきました。
早速発表資料作りに取り掛かろうと思ったものの、上記の三つの実装のうち「案1. レシーバを破壊的に変更するようなメソッドで++
を置き換える」と「案2. 字句解析時に++
を読み込んだら+=1
を再現するような処理を行う」はあまりにもコンテキストが強力すぎて、これをうまいこと説明できる気がまったくしません。
ということで、++
を構文的に有効にするまでの一通りの流れを説明する用のシンプルな実装が必要だと思い、これを追加しました。
ここまで散々苦労してきたので、この実装は10分くらいで終わりました。練度✌️
(ちなみに) 後置演算子++
の話
ところで、今回の発表でご紹介しているi++
のようなスクリプトは後置演算子なので、++
よりも先にi
が評価された結果i++
の返り値自体はi
そのものになるのでは…と言うご指摘を発表後、複数名の方からいただきました。全くもってその通りです。
すみません、そこまでは実装する余裕がありませんでした。i
を先に評価する、というのはもう一段階挑戦が必要そうな気がするので、今回の発表でパーサに興味を持ったどなたかに試してみてほしい…
(ちなみに) 最終的なスライド枚数
ここまでの実装についての解説にスキャナとパーサの一般的な挙動の解説を加えて発表資料を完成させたところ、最終的に今回のスライド枚数は182枚になりました。過去最多!
上述の通り発表資料の英語に自信がなかったため大倉さんにレビューしていただきました。お手数おかけしました…🙏
RubyKaigi 2023 参加日誌
さて、ここからはそうしていよいよ迎えたRubyKaigi 2023の様子です。
(以降、会期中のツイート多め。いくつか他の方のツイートも引用していますので、もし問題がありましたらお手数ですがお知らせください。)
DAY0 (5/10)
遅ればせながら行ってきます🚃
— Misaki Shioi (しおい) (@coe401_) 2023年5月10日
周りにいる人が全員Rubyistな気がしてくる。 pic.twitter.com/8vh5lM2yER
あずさに乗って出発。
到着!お出迎えうれしい!! #rubykaigi pic.twitter.com/Praui5Adw8
— Misaki Shioi (しおい) (@coe401_) 2023年5月10日
松本駅に到着。お出迎えをいただきました。
この日の晩は現地の銭湯、塩井乃湯へお邪魔しました(Twitterでずっっっと「之」とtypoしていてすみません…)
塩井之湯、とっても良い湯でした…♨️ #rubykaigi
— Misaki Shioi (しおい) (@coe401_) 2023年5月10日
(ちなみに名前はミネラル分の多い泉質に由来するものとのこと。塩井さんにゆかりの湯というわけではなかった) pic.twitter.com/G3ri3CATEj
大正時代に建てられたという風情のある建物とミネラル分豊富な泉質で体が芯から温まるお湯をたのしむことができる素敵な銭湯でした。
わたしも塩井と申します、という話題からおかみさんとたくさんお話しできたのもうれしかったです。
公式サイトhttps://www.mcci.or.jp/www/sioinoyu/
DAY1 (5/11)
おはようございます #rubykaigi pic.twitter.com/6oHfpd5Vn0
— Misaki Shioi (しおい) (@coe401_) 2023年5月10日
女鳥羽川。
最高 #rubykaigi pic.twitter.com/5LsTR9yYNF
— Misaki Shioi (しおい) (@coe401_) 2023年5月11日
珈琲茶房かめのやのモーニング。
松本には行ってみたい純喫茶が行き尽くせないほどたくさんありますね。
#rubykaigi 会場に着いた!よろしくお願いします! pic.twitter.com/8xgPdyorhF
— Misaki Shioi (しおい) (@coe401_) 2023年5月11日
#rubykaigi pic.twitter.com/SDt0L7aJP7
— Misaki Shioi (しおい) (@coe401_) 2023年5月11日
会場に到着。たくさんの旗やのぼりが迎えてくれました。まつもと市民芸術館はとても素敵な会場で、特にメインホールは迫力があり、参加者としても気持ちが盛り上がりました。
この日はこんな感じで過ごしました。
- Matz Keynoteを聴く
- Ruby30周年ということで歴史のお話(大好き)
- 先日のRuby30周年記念イベントで高橋さんからもRubyが歩んだ30年を振り返るお話がありましたが、今回はまつもとさんから見たRubyの歴史ということで、プログラミング言語開発にまつわる生きた教訓を交えたお話となりました
- 初日のランチは一緒に参加していた会社の人々のうち、松本出身のメンバーの紹介で美味しいお蕎麦をいただきました。お店の名前を失念…
- 休憩中に五十嵐さんからRubyとRailsの学習ガイド2023を購入。これはWebアプリケーション開発の全体を見渡すいい本なので、特に最近Webアプリケーション開発を学び始めたという方におすすめです。
- ランチ後The future vision of Ruby Parserを聴く
- 自分の発表でも大変お世話になった金子さん。個人的に今年一番好きなトークでした。
- MRIのパーサの現状の課題とこれから先こうなると嬉しい、に対して正面から立ち向かい、次から次へと訪れる困難をばったばったと薙ぎ倒しながらパーサを開発されている様子が伺えて圧巻でした
- Ruby Parser開発日誌を読んで迎えたので、内容の半分くらいはつかめたかな…??という感じ
- 難しいんだけどもトークも面白いのですごい
- パーサジェネレータLramaについては事前にAsakusa.rb Welcome Drinkupでお会いした際に「僕らはエンジニアなので入力(今ある既存のparse.yをどう生かすか)のことも考えないといけない」と仰っていて格好いいなと思いました
- その後UTF-8 is coming to mruby/cを聴く
- その後のおやつ休憩の際、ログ処理について勉強させていただきます、ということでtagomorisさんからFluentd実践入門を購入。当日会場最後の一冊でした!
モリス本完売! #rubykaigi
— joker1007 (アルフォートおじさん) (@joker1007) 2023年5月11日
- 休憩明けにPower up your REPL life with typesを聴く
- みんな大好きTRICK 2022 (Returns) Gold Medalist ぺんさん
- katakata_irbについては以前がFukuoka.rbミートアップにいらしていた際に教わったのですが、その便利さとこれをどうやって実現しているのかさっぱりわからず感動しました。
- 発表を聴いていて、技術的な側面では全然理解できている気がしないのですが、Rubyの柔軟な文法をサポートするために一つずつ丁寧に仕事をこなしていらしてすごいな〜と思いました
- 続いてLightning Talksを聴く
- 初日のセッションはここまで
- 夜はOfficial Partyへ。ここで初めましての方や、なかなかお会いする機会のなかった憧れの方や、ちょいちょい顔は合わせるのだけどじっくりお話しする機会のなかった方とたくさんお話しできました。もっと話したかったな〜
- あと人と人のご縁を取り持つお手伝いができたりした場面もあったのでよかった…
#rubykaigi 一日目、刺激的な一日だった…!
— Misaki Shioi (しおい) (@coe401_) 2023年5月11日
相変わらず発表はわかったりわからなかったりして置いていかれているのだけど、すごいRubyistたちが皆さんたのしそうにお話しされていて嬉しくなってしまった。
廊下でもパーティでも色んな方と沢山お話して気持ちが高まったので、明日の発表がんばります! pic.twitter.com/nue4We4zX9
DAY2 (5/12)
#rubykaigi 二日目!快晴!! pic.twitter.com/CpeeN14CmU
— Misaki Shioi (しおい) (@coe401_) 2023年5月12日
この日は朝一で同時通訳の方々との打ち合わせがあったので喫茶店抜きで直接会場へ。
あの大量のスクリプトを捌いてくださった同時通訳の方々にとても感謝しております🙏
朝一で聴いたセッションは咳さんのLearn Ractorでした。
一緒に観ていたmoroさんが初っ端の「Concurrency is everywhere」というキラーフレーズにやられていたのがすごいよかったです。わたしは「Ractor間をまたぐ値はdeep copyされる」→dRubyっぽい!!「Ractor.make_shareable
された値はfreezeされる」→DRbUndumpedっぽい!!!!というお話に興奮していました。昨年に続きこれぞプログラマ、というトークで痺れました。
自分の出番は咳さんのすぐ後でした。
#rubykaigiC にてこの後10:20よりお話しする「Implementing "++" operator, stepping into parse.y」の発表資料です。
— Misaki Shioi (しおい) (@coe401_) 2023年5月12日
This is a slide from my presentation at RubyKaigi 2023. https://t.co/g0XyKGvVqf
よろしくお願いします! #rubykaigi
前日の金子さんのトークで会場内のパーサ熱が高まりに高まった結果、思いがけず本当にたくさんの方がトークを聴きにきてくださいました。
本当にありがとうございます。部屋に入れなかった、という方もいらしたようなので、もしよければ後日アーカイブなどをご覧いただけるととても嬉しいです。
会場のRubyistたちのあたたかい雰囲気に助けてもらい無事に発表を終えました!!!!
— Misaki Shioi (しおい) (@coe401_) 2023年5月12日
ありがとうございました!!!! #rubykaigi https://t.co/1vZVYSi65X
始まるまでは緊張していたのですが、いざ話し始めてみると会場の雰囲気があたたかかったおかげで、これまでで一番リラックスしてお話しできた発表になりました。
(あとはもしかすると去年の件でちょっとだけ肝が据わったかも…?)
自分の発表の後、この日はこんな感じで過ごしました。
- Yet Another Ruby Parserを聴く
- その後のランチ休憩中にとりいさんからユウと魔法のプログラミング・ノートを購入
- 会場でのちょっとした空き時間に冒頭部分を読み、やさしい語り口に早速ぐいぐい引き込まれてしまいました。帰ってきてからまだばたばたしていて読み進めることができていないのですが、早く続きが読みたい!
- お昼ごはんは何人かの方とご一緒し、この日はお蕎麦ではなく美味しい焼き肉をいただきました。お店の名前を失念…
- 時間の都合上、ランチ直後のトークに間に合わず😂
- ランチ後はとりいさんのReading and improving Pattern Matching in Rubyを聴く
セッションを経て翌日の様子(parse.yとcompile.cは神がかり的所業)
今日はしおいさんと
— やきとりい (@yotii23) 2023年5月13日
「parser.y読むのすごい」
「compile.c読むのすごい」
って言い合ったのがよかったです。
- その後Fitting Rust YJIT into CRubyを聴く
- 2日目の最後、MaximeさんによるKeynote、Optimizing YJIT’s Performance, from Inception to Productionを聴く
- この日のセッションはここまで
- 帰る前に角谷さんに研鑽Rubyプログラミングへサインをいただきました
2日目が終わっての感想。
#rubykaigi 二日目たのしかった!!(自分の出番も終わってひと安心…)
— Misaki Shioi (しおい) (@coe401_) 2023年5月12日
色んな人のお話を会場や廊下で聴いて、どんな偉業も時間をかけた試行錯誤の先に成されるのだな、これがエンジニアリングなのだな、と思ったりしていました。
まだまだお話ししたい人々が沢山いるので、明日もよろしくお願いします! pic.twitter.com/WMxXf32ykG
写真は自分の発表後にmiwaさんからお土産にいただいたhikari no caféさんのおやつです!(自慢)
大切にいただきました。ありがとうございます!
この日はこの後会社の人々と晩ごはんをいただいたのですが、その間にRubyのmasterではLramaがBisonを置き換え(これにより金子さんはいわゆる"The Bison slayer"の異名を得て)、Ruby 3.3.0-preview1がリリースされていました。すごい!!!!
Ruby 3.3.0-preview1 Released https://t.co/2Uwfg2NmOF
— Ruby Programming Language (@rubylangorg) 2023年5月12日
夜、チームの人々と飲んでいる間にRuby 3.3.0-preview1がリリースされていてめでたい㊗️
— Misaki Shioi (しおい) (@coe401_) 2023年5月12日
(この夜は本当はもう少し遊び歩きたかったのですが、ほんのちょっとだけ疲労もあり、体調優先で早寝しました)
DAY3 (5/13)
おはようございます #rubykaigi pic.twitter.com/JQiDSlp0Cp
— Misaki Shioi (しおい) (@coe401_) 2023年5月12日
朝は今回Rubyistたちに大人気だった珈琲美学アベへ。
モカクリームオーレとても美味しかったです。
#rubykaigi 三日目もよろしくお願いします(給水完了アピール) pic.twitter.com/LRrpuVtxAV
— Misaki Shioi (しおい) (@coe401_) 2023年5月13日
「松本市はお水がおいしい」という事前情報を得ていたので毎朝マイ水筒に水を汲んで会場に参じていました。
とうとう最終日、ということで朝一でRuby Committers and The Worldが始まる前にえもりさんとやださんからはじめてつくるWebアプリケーション〜Ruby on Railsでプログラミングへの第一歩を踏み出そうを購入しました。
こちらははじめてプログラミングを学ぶ方向けの書籍ではあるのですが、Webアプリケーション、のWebのところに最初からしっかりフォーカスが当たっていてこれは良書だなと思いました。
自分が誰かに(Web)プログラミングについて伝える際(e.g. Rails Girlsにコーチで参加するときとか)に上述の「ユウと魔法のプログラミングノート」と「はじめてつくるWebアプリケーション」を読んでおくといい効果が期待できそう。
(もうお一人の著者であるcobachieさんにもサインをいただく気満々だったのですが、その日のうちにお話しする機会がなくサインをいただき損ねてしまいました。これは松本にもう一度伺うしか…??)
そうして始まった「Ruby Committers and The World」。
ここまでですでに色々ありすぎて処理しきれない最高たのしい #rubykaigi pic.twitter.com/AZuWdHmQNS
— Misaki Shioi (しおい) (@coe401_) 2023年5月13日
今回も最高でしたがパーサの話題だったり正規表現の話題だったりetc...の重要トピックについて議論が交わされ、Rubyの未来についてちょっとしんみりしているところへAaronさんによるRuby 4へのご提案で会場が笑いに包まれたのでした。ちょっと笑いに貢献できて嬉しい。
この後、この日はこんな感じで過ごしました。
- Build Your Own SQLite3を聴く
- 最終日のランチは流れで何人かの方とご一緒させていただき、美味しい鴨つけそばをいただきました。やっぱりお店の名前を失念…
#rubyfriends pic.twitter.com/VyjFOFNC1V
— anna (@ae__B_) 2023年5月13日
- ランチ後Ruby vs Kickboxer - the state of MRuby, JRuby and CRubyを聴く
- トークの合間に金子さんから一日目のLTの続き(幻のAdvanced編)を披露していただく
- ここから先がまたとてつもなく面白かった
- Rubyの柔軟な文法を叶えようと色んなハックで頑張っているのがわかるのでおすすめです。聴いているうちparse.yの向こうに人がいる…!という気持ちになっていました。
Advanced 説明会が行われてました@spikeolaf @coe401_ #rubykaigi #rubykaigi2023 pic.twitter.com/MJkITdsm97
— えりりん (@suuuuengch) 2023年5月13日
- ここ辺りからちょっと色々ばたばたしていたり、聴きたかったトークが満席だったりして基調講演までホールに戻れず
- その代わりに色んな人とじっくりお話しする時間をとれたのでそれはそれでよかった…
- 最後にSoutaroさんによるClosing Keynote Parsing RBSを聴く
そして、Closing Keynoteの後、とうとう閉会の時間がやってきました。
2017年に始まりコロナ禍を経て松本でRubyKaigiを開催するに至るまでの長い道のりと、とうとうそれを実現したNiceなTeamの皆さんが壇上から手を振る姿に、どれだけ拍手を送っても足りない気持ちでした。
#rubykaigi 三日目、最高のKaigiをありがとうございました!!!!
— Misaki Shioi (しおい) (@coe401_) 2023年5月13日
また来年!!!! pic.twitter.com/WhX4KhNve0
本当にありがとうございました。
RubyKaigi 2023は夢のような奇跡のような、あっという間の3日間でした。
今年は初参加の方もたくさんいらしていたという印象ですが、初めての人々にもこの感じを持って帰ってもらえますように。来年また沖縄で集まることができたら嬉しいなと思います。
この後はSTORESさん主催のAfter Partyに参加したり
このパーサ関係者感さいこう #rubykaigi pic.twitter.com/psCKC4zEFH
— tagomoris (@tagomoris) 2023年5月13日
その後中田さんとゆうぞうさんについていったらその先でこんなことになったり
パーサーを1から教えてください!!
— 😺 (@neko314_) 2023年5月13日
の図#rubykaigi pic.twitter.com/vpUtFqaJIf
最終的に懐かしのTama.rbになったり
偶然に偶然が重なって、三日目の最後にTama.rbのみんなで集まることが出来ました!!コミュニティはコロナ禍で解散してしまったけれど、こうしてまた集まれて、「また来年沖縄で!」なんて約束も出来て、最高の思い出になりました。ありがとうRubyKaigi!!
— けん (@ken3ypa) 2023年5月13日
#rubyfriends pic.twitter.com/xnkLdZPVUP
そして翌朝はこうなる。
RubyKaigiの夢ばかり見て、早く会場に行かないと、あの人ともこの人ともお話ししたいし…と寝ぼけながら目が覚めたけど、今日はもうRubyKaigiはないんだった…寂しい。
— Misaki Shioi (しおい) (@coe401_) 2023年5月13日
実は次の日ものんびり松本観光をしようと街を歩いていると色々とたのしい出来事があったのですが、夕方には無事に帰路につき…
帰宅!お疲れさまでした!! #rubykaigi pic.twitter.com/PSWCguqnYM
— Misaki Shioi (しおい) (@coe401_) 2023年5月14日
終わってみて一つだけ後悔しているのは、会期中もっと気軽にたくさん色んな人々と写真を撮っておくべきだったな、ということです。
せっかく#rubyfriendsというハッシュタグがあるので、これに託けて来年はもっと写真を撮れたらいいな。
ということで、今年も来年以降もわたしの写真は自由にアップロードしてくださって問題ありません(その際にメンションを頂けると嬉しい!)
RubyKaigi 2024
— RubyKaigi (@rubykaigi) 2023年5月13日
Naha, Okinawa
May 15th..17th, 2024#rubykaigi
来年もよろしくお願いします!
その他に書き残しておきたいこと① 「無名の質」、そしてNice Teamのみなさんへ
「無名の質」という言葉を噛みしめる
— Misaki Shioi (しおい) (@coe401_) 2023年5月13日
Kaigiの間、「RubyKaigiとはいかなる場なのか」を表現するため何度か目にしたり耳にしたり自分でも口にした「無名の質」という言葉があります。
この言葉の出典は建築家クリストファー・アレグザンダーによる「時を超えた建設の道」です。わたし自身は「パターン、Wiki、XP」を読んでいて初めて知りました。
RubyKaigiという場は、端的に言葉で表現しようとすると「たのしい」だったり「最高」のような、それは本当にそうなんだけれどもそれだけではとても言い尽くせないよさを持つ場です。
ある種の混沌の中であらゆることがあらゆる場所であらゆる人の身に、魔法のように同時多発的に有機的に発生していて、それが人々を生き生きとさせているのだと思います。このよさをうまいこと言えないのは、それが名前のつけられない「無名の質」だからなのでしょう。
こうした場を作ってくださったオーガナイザーとヘルパーの皆さん、Rubyコミッターと登壇者の皆さん、そして参加者の皆さんにとても感謝しています。また、自分がそのうちの一人であったことを嬉しく思います。
特に2017年から松本でのRubyKaigiを実現しようと奔走されていたオーガナイザーの皆さんにはこの7年間、大変なご苦労があったと思います。本当にお疲れ様でした。
その他に書き残しておきたいこと② 「同じコミュニティの中の人同士になっていく」ということ
RubyKaigiを終えて改めて感じたことのうち一つです。
初めての人と会う時はお互い手探りなので、相手の持っている客観的な情報から相手がどんな人なのかを想像するしかないのだけど、お話しするうち自分にとってその人が「そうした情報を纏った人」ではなくて「その人そのもの」になっていくのがとても嬉しい。RubyKaigiでもそんな場面が何度もあった。
— Misaki Shioi (しおい) (@coe401_) 2023年5月17日
RubyKaigiで人とお話ししていると、そのうちだんだん相手が「こういう客観的情報を持った人」でありかつ「自分がいるのと同じコミュニティの人」でもある、と実感できる瞬間があったりして、そうした瞬間がわたしはとても好きです。
それが「コードの向こうには人がいる」を肌身で感じることができる瞬間であるためです。そしておそらくそれは相手の方にとっても同様なのだろうと思います。
わたしはRubyコミュニティに出会うまでずっと人付き合いに苦手意識を持っていたので何か不思議な感じがしますが、こうして人同士が対話をし、同じ時間を過ごすうち「同じコミュニティの中の人同士」になっていくのだな、という気がしています。
(と思ったら3年前の自分がすでにそれを大江戸Ruby会議08でお話ししていたのでえらい…)
その他に書き残しておきたいこと③ 2024年に向けて
今回は想定外に沢山の人々に発表をたのしんでもらえて本当に嬉しかったのだけど、それと同時に今日、未来への宿題を頂けたのが一番良かったなと思う。
— Misaki Shioi (しおい) (@coe401_) 2023年5月14日
何から始めたら良いかさっぱりわからないので時間はかかるかもしれないけど、自分なりのたのしさに沿ってやっていきたいな。
最終日の翌日に角谷さんから発破を掛けられたのもあり、この後は元々の興味にちょっと方向性を戻して再びネットワーク方面を勉強していこうかなと思っております。
会期中、ゆうぞうさんに「ネットワークの世界は広くて深い沼なので(というかコンピュータの世界全体がそうなのですが)、どこから手をつけたら…」という相談を持ちかけたところいくつかヒントをいただけたので、とりあえず足場からこつこつ固めていきたいです。
まずはそのとっかかりとしてちょうどKaigi直前に公開されていたRubyKaigiとDNS-over-HTTPSとDDRを読んでみたところ、(ちゃんと内容を理解はできている気はしないけど)KaigiのWiFiを支えるNOCの皆さんが自在にネットワークを操っておられる様子に感銘を受け、今の時点では割と苦手意識のあるDNSについてちゃんと勉強してみようと思い立ち、結果こうなりました(※)
わたしの今のところの #kaigieffect は昨日池袋のジュンク堂書店で買った「DNSがよくわかる教科書」と「ピアリング戦記」です(???) pic.twitter.com/2dtnVhq5LM
— Misaki Shioi (しおい) (@coe401_) 2023年5月16日
引き続きがんばります!
(※後日Cookpadさん主催のアフターイベントでこの記事を執筆された花月さんにご挨拶できてよかったです。その際そらはさんから「異常KaigiEffect」と呼ばれました)
Ruby Advent Calendar 2022 part2 (15日目): 「Webで使えるmrubyシステムプログラミング入門」 (mrubyシスプロ本) 読書日記 (※2年越し)
Ruby Advent Calendar 2022 part2 15日目の記事です🎄
昨日は@rsym1290さんによる「AWS SDK for Ruby V3のスタブを使ってみる」でした。
まえがき
2020年11月25日に発売された udzuraさん著・Webで使えるmrubyシステムプログラミング入門 (mrubyシスプロ本) の読書記事です。
実は本書の執筆中、レビューに参加させていただくという大変貴重な機会をいただいていたのですが、出版当時はまだわたしが自ブログを持っていなかったためにブログ記事を書くことができていなかったのでした…
時は流れて今年、mruby組み込みWiresharkを作ろうと思い立った(参考: RubyKaigi 2022に現地参加 & 登壇しました)際、その実装の参考にしようと再読してみたところ改めてめちゃめちゃたのしく勉強になったため、この機会に大変大変遅ればせながら、2年越しに感想を交えながら記事を書いてみたいと思います。
奇しくも2022年はmruby誕生10周年の記念すべき年でしたね。おめでとうございます🥳
どんな本?
出版社サイトより
本書はシステムプログラミングをテーマに、mrubyの基本と活用法を学ぶことを目的とした技術書です。 システムプログラミングとは何かをはじめ、mrubyの概要、開発環境の構築、コマンドラインツールの実装、C言語とmrubyの連携、Apache HTTP Server にmruby を組み込む方法、安全にコードを書くために必要な知識などを丁寧に解説しています。付録ではシステムプログラミングのためのコマンドラインツールを紹介しています。
上記の通り本書で取り扱っているトピックは非常に広い範囲に渡っているため、mrubyの本として、システムプログラミングの本として、あるいはセキュリティの本として…などいくつもの観点から読むことができます。
mrubyでのプログラミングを通じて、それぞれのトピックを深く学んでいくためのとっかかりを与えてくれるような一冊となっています。
わたしの場合は冒頭に述べた通り、今回はmrubyをWiresharkに組み込みたい、というモチベーションのもとmrubyによるソフトウェア組み込みについて学ぶため再読した際、本書の特にCHAPTER 03の前半とCHAPTER 07が実装のための大きなヒントをくれました。
今後もまた立場を変えて再び別の切り口から本書を開き、新たな発見に出会うことがありそうだなと思っています。
あると良さそうな前提知識
本文中でも明記されているのですが、初めて読み始める前に以下のような知識の土台があるとより楽しめそうです。
- 普段使いしている程度のRubyの知識
- かじったことがある程度のC言語の知識
- Head First C や 苦しんで覚えるC言語を読み終えたくらい
- Apache Web Serverを触ってみたことがある程度の経験
- ゼロからわかる Linux Webサーバー超入門を読んで動かしてみたくらい
各章について
CHAPTER 01: システムプログラミングへの招待
システムプログラミングとはどんなものか、mrubyとはどんなものか、という解説に続いて「本書がどんな人に向けた本なのか」がわかる章です。
わたしは普段Railsを使ったWebアプリケーション開発の仕事をしているのですが、例えばそういった人があえてシステムプログラミングに、あえてmrubyで入門してみることでどんな発見を得られるのか、あるいはインフラエンジニアやSREの方、低レイヤの技術やmrubyそのものに興味がある方へ本書がどのような知見を与えてくれるかが述べられています。
CHAPTER 02: mrubyに触れてみよう
この章で早速mrubyをビルドしてHello Worldしてみたりmgemを利用してmrubyをカスタマイズしてみたりします。環境を用意するところから実行ファイルを作成するまでの道のりが一歩ずつ丁寧に解説されています。
わたしは本書をきっかけに初めてmrubyに触れたため、この章を読んで「rake
コマンド一つで手軽にmrubyをビルドできる」そして「mgemを利用すると自分だけのmrubyをビルドできる」というmrubyならではの体験に感動しました。
CHAPTER 03: mgemを作ってみよう
「mgemを作ってみよう」というタイトルの章ですが、前半は前章を受けてmrubyバイナリがどのようにして実行可能な状態になるのか、そのビルドパイプラインの流れが解説されており、ここでmrubyについての基礎知識を学ぶことができます。
この前半部分は、本書を一周した後で改めてmrubyをちゃんと理解したいという気持ちのときに読み返して点と点が繋がる感覚がありました。
後半はmrubyプログラミングの手始めに、mruby本体に組み込むためのライブラリであるmgemをテンプレート(とても便利)から作成し、テストを追加し、実際にmrubyに組み込んで動作させてみます。
mgemを公開する方法まで解説されているため、実際にmgemを自作したい時にも参照できそうです。
CHAPTER 04: mrubyでシステムの状況を調べる
この章からいよいよシステムプログラミングについての学習が始まります。
導入部分で早速ps
コマンドやstrace
コマンドに触れ、その後プロセスの様子を観察するmgemの開発を通じてLinuxの/proc
について学んでいくことで深淵なるシステムプログラミングの世界に一歩足を踏み入れることができます。
とはいえこの章ではそのためのコードをRubyで書くので、初めてのシステムプログラミングでもとっつきやすく感じました。
また前章に引き続きmgemを開発してmrubyに組み込む、という流れに沿って開発を進めるため、mrubyについては前章までのおさらいもできます。
CHAPTER 05: C言語でmrubyを拡張する
システムプログラミングの深淵にもう一歩踏み込むため、この章ではシステムコール(uname(2)
、stat(2)
)とC言語とmrubyのC APIも駆使してシステム情報を取得するためのmgemの開発を行います。
まずはC言語でを扱う簡単なプログラムを書くところから始まり、その後はmgemの中でC言語(mrubyのC API)を用いたRubyプログラミング(!?)に入門することができます。
さらに最後にはgdbを利用してC言語でのデバッグも体験できるという、お得で読み応えのある章でした。
CHAPTER 06: C言語の複雑なデータをmrubyで扱う
この章では、前章でも登場したシステムコールstat(2)
とmrubyの仕組みを更に深掘りし、mrubyから扱うことができるようにしていきます。
難易度的には本書の中でも一つの山場のように感じた章でした。mrubyはインスタンスのデータをどのように持っているのか(「Rubyのしくみ」第5章が思い起こされます)であったり、mrubyを介してメモリ管理の仕組みがないC言語レベルのデータをどのように扱えば良いのか、といった難しい話題(自分比)に踏み込んでおり、読むたびに新しい発見があってびっくりしています。
システム情報を格納するStat構造体の持つ各情報に関する小ネタも豊富に詰まっています。
また、この章でも最後にvalgrindを利用してメモリリークの検知を体験することができます。こうした便利ツールの使い方や、プログラムを修正するときの考え方を学ぶことができるのも本書の魅力です。
CHAPTER 07: Apache HTTP Serverの中でmrubyを使おう
ここまでの章ではmgemを作成し、それを組み込んだmrubyを手元で動かしてみる、といった流れで解説が行われてきました。
このCHAPTER 07と次のCHAPTER 08では、いよいよmrubyの本領の一つ、mrubyによるソフトウェア組み込みを体験することができます。
いずれの章でも組み込む対象となるソフトウェアはApache HTTP Serverです。
まず本章ではApacheの拡張機構として書かれたmod_mrubyを実際にApacheに組み込み、RubyでApacheの設定を書いてみることによって、「mruby自体をソフトウェアに組み込む、とはどういうことなのか、それによってどんなことができるようになるのか」といったイメージを掴んでいきます。
この章はmod_mruby入門として活用できそうなくらい手厚くmod_mrubyについて解説されているので、そういった用途にも便利そうです。
CHAPTER 08: Apacheの拡張モジュールにmrubyを組み込む
クライマックスの章です。CHAPTER 07では実在のApache拡張であるmod_mrubyをApacheに組み込みましたが、この章では1からApacheにmrubyを組み込んでいきます。
C言語・mrubyのC API・Apacheの拡張用APIを駆使してのプログラミング、rakeを使ったモジュールのビルドとインストール、abやperfを使ったパフォーマンスチューニングなどトピックも大盛りです。
rakeタスクの定義は本文中ではさらっと解説されているのですが、この辺りを読んでいて自分がrake(make)について何も知らなかったことがわかりました。
難易度的にもクライマックスなのですがその分勉強になることも多く、Apache以外のソフトウェアにmrubyを組み込むような場合にも非常に参考になりました。
この章がなければWireshark with mrubyは完成しなかったと言っても過言ではない…
CHAPTER 09: 安全なプログラムを書く
最終章は前章までとはちょっと趣を変え、セキュリティのお話です。
C言語でプログラムを書く際に埋め込んでしまいがちないくつかの脆弱性について、そしてそれらの中でバッファオーバーランを例に取り、それを作り込まないための方法論について考えていきます。ここでmrubyのC APIがどのように役立つのかは必見です。
安全なプログラムを書くことの難しさと、それでもそれを目指していかなくてはいけない、という意識の大切さと、そのための実践的な心構えが説かれています。
APPENDIX
CHAPTER 09にてこれでおしまい、めでたしめでたし…かと思いきや、最後に50ページ越えの特大付録がついてきます。
本文中に登場したものを中心に、Cプログラミングやシステムプログラミングの味方となるコマンドラインツールたちについて丁寧に解説されています。便利。
EPIROGUE
謝辞に名前を掲載してもらえて嬉しい✌️
技術者としてmrubyシスプロ本の次のステップを踏んでいくことについてうづらさんの熱い思いが伝わってくるあとがきでした。
おわりに
今年はmrubyシスプロ本とYamanekkoさん著・入門mruby Cからmruby APIを使いこなす(そしてWiresharkの開発者ガイドとThe dRuby Book)のおかげでRubyKaigiに登壇できました…本当にありがとうございます。
リファレンス的に参照するなら入門mruby、実践的な使い方を参照するならmrubyシスプロ本、と需要をカバーする本が揃っていてうれしいですね。
mrubyの方は出版時点からバージョンが上がってますます良くなっていっているのですが、いずれも今なお役立つ普遍の教えが詰まった名著だと思います。
普段はMRIを使っているけれど、mrubyってどんな感じ…?という方も、たのしいソフトウェア組み込みの世界を体験する際のお供にいかがでしょうか?
それでは素敵なクリスマスをお過ごしください🎁
RubyKaigi 2022に現地参加 & 登壇しました
しおいです。
みなさまRubyKaigi 2022お疲れ様でした!
わたしはありがたいことに去年に続き、DAY2に登壇する機会をいただきました。
今年は3年ぶり2回目となる現地参加となり、本当に楽しいあっという間の3日間を過ごすことができました。
この記事では、今回のテーマを選んだきっかけ、実際に作ったもの、登壇本番のことや会期中のあれこれを振り返ります。
Wireshark + mruby + dRubyのお話をするに至ったきっかけ
今回は「Packet analysis with mruby on Wireshark - dRuby as example」というタイトルにて「mrubyを組み込んだWiresharkでdRubyパケットを解析する」という内容でお話をしました。
こうした登壇テーマを選ぶに至ったのは、去年2021年のRubyKaigi Takeout 2021で「Ruby likeなアプリケーションプロトコルを作る」という内容のお話をした際、何人かの方から「dRubyっぽい」との感想をいただいたのをきっかけにdRubyの勉強を始めたことに端を発します。
次はわたしの2つ目の #kaigieffect であるところの「dRubyによる分散・Webアプリケーション」をこつこつ読む。 pic.twitter.com/ZsFk0NPH6e
— しおい (Misaki Shioi) (@coe401_) 2021年9月16日
dRubyはとにかく面白く、またそのときちょうどWiresharkに入門したばかりでもあったため、その年のRuby Advent Calendarのネタとして「dRubyパケットをWiresharkでキャプチャする」という試みを思いつきました。
そうして出来上がったのがこの記事です。
結論を書くと、
- WiresharkでdRubyパケットをキャプチャしようと思ったが、WiresharkはdRubyを解析可能なアプリケーションプロトコルとしてサポートしていないので、トランスポートプロトコルまでしか解析できなかった
- …と、いうのは誤解で、後日気がついたところによると実はWiresharkに最初から組み込みのdRubyディセクタをONにすれば解析できた (後日追記)
という内容の記事です。
なお、Wiresharkにおいてはディセクタなるプラグインによってプロトコルごとにパケットを解析できる、そしてそのディセクタは自作することができる、ということは「ネットワークプロトコルハッカーズガイド - キャプチャ、解析、エクスプロイトの理論と実践」を読んでいて初めて知りました。
(ちなみにこの本は良い本なのですがわたしには難しく、一応通読しましたが何ひとつ理解できてません)
ところで、たまたまこのとき同時並行でudzuraさんの「Webで使えるmrubyシステムプログラミング入門」を再読していました。
(こちらも良書です。今回めちゃめちゃ勉強になりました)
この本の中に、Apache HTTP Serverの拡張モジュールにmrubyを組み込んでApacheの中でRubyを扱う、という面白い例が登場します。
ApacheはCで書かれており、そしてわたしが入門したばかりのWiresharkもCで書かれています。
これは、もしかするとWiresharkにmrubyを組み込めばWiresharkの中でもRubyを使うことができるのでは、つまりmrubyを組み込んだWireshark + Rubyで書いたWiresharkディセクタでdRubyパケットを解析できてしまったりするのでは…!?(???)と夢が広がっていきました。Ruby大好きなので。
mruby on Wireshark
ということで実装したのがこちらです。
Wiresharkにmrubyを組み込むため、Wiresharkのリポジトリの中にmrubyのリポジトリをGitサブモジュールとして置いておいて、ビルド時に力技でmrubyをリンクさせるような方法を取りました。
ホストマシンにmrubyをインストールさせてリンクさせる方法も考えたのですが(登壇後にもそのような指摘をいただきました。実際、同じくWiresharkに組み込まれているLuaはそういう方法を取っているようです)、mrubyは柔軟にカスタマイズすることができるため、ユーザーが「Wiresharkに組み込むためのmruby」を常に持っていてくれる保証はないかもしれないと考え、このような方法を選びました。
が、mrubyのリポジトリを丸ごとWiresharkの中に置くのではなく、ビルド済みのlibmruby.aを直接リンクさせる方が良いかもしれない…
この辺りは自分に知見がないために難しく、ぜひ詳しい方にお話を伺ってみたいです。
また何せネットワークもソフトウェア組み込みもdRubyも初心者なので、実装にあたってはC、mruby、Wireshark、CMake、dRuby、RubyのMarshalフォーマットの勉強が必要でした。
参考にした書籍・記事・ドキュメント・ソースコードは以下のようになります。
- Head First C
- 詳説 Cポインタ
- Webで使えるmrubyシステムプログラミング入門
- 入門mruby Cからmruby APIを使いこなす
- 実践 パケット解析 第3版
- 9.2. Adding a basic dissector (Wireshark Developer's Guide)
- packet-drb.c (WiresharkのdRubyディセクタのソースコード)
- Step 2: Adding a Library (CMakeチュートリアル)
- 勝手に作るCMake入門 その1 基本的な使い方 (かなりお世話になりました)
- 勝手に作るCMake入門 その4 外部ライブラリを利用する (同上)
- dRubyによる分散・Webプログラミング
- ruby/drb (dRubyのソースコード)
- Marshalフォーマット (るりまのMarshalフォーマットの紹介)
あとmrubyをCに組み込む勉強をしていたときの副産物として、Fukuoka.rb 0x100 回 LT 大会 (#256)でこんなLTをしました。
当初やりたかったことを実現するため結果的にWireshark、mruby、dRubyと話題が発散しすぎてしまったような気がしていたので、登壇前はどれだけの人に楽しんでもらえるかなとちょっと不安だったのですが、登壇後には予想以上の反応、温かい感想をいただきました。
本当に嬉しいです。
RubyKaigi 2022!!
こんな感じで出したプロポーザルが無事通り、準備期間中必死に書いた160枚超の発表用スライドを携え、(ついでにRubyKaigiとは全然関係ないのですがKaigi直前に行っていた転職活動も成功し、そして現職場への引き継ぎも何とか無事終えて、)RubyKaigi本番に臨みました。
(以降、会期中のツイート多め)
つ #rubykaigi pic.twitter.com/lLFuTp3oHv
— しおい (Misaki Shioi) (@coe401_) 2022年9月8日
来ました!!!! #rubykaigi pic.twitter.com/G8pR49djHJ
— しおい (Misaki Shioi) (@coe401_) 2022年9月8日
Rubyistが沢山いて楽しい!!!!
— しおい (Misaki Shioi) (@coe401_) 2022年9月8日
会場に着くと、当たり前ですがそこには沢山のRubyistたちが集っていました。
久しぶりに会う人や、初めてin personで会う人や、憧れの人までも。
3年ぶりに人々と顔を合わせ、おしゃべりをし、一緒に難しい話を聴く(そしてその難しさにスッと置いていかれる)、そして現地の美味しいものをいただく、というのはこんなに楽しいことだったのだな、と胸がいっぱいになりました。
いやー難しい話を沢山聴くことができてだいぶ頭がほかほかになったし、久しぶりの人や初対面の人や憧れの人と沢山お話できて最高のDay1でした。
— しおい (Misaki Shioi) (@coe401_) 2022年9月8日
明日発表がんばるぞ!! #rubykaigi
(ビビッドガーデンさんのブースで同窓会みたいになった図↓) pic.twitter.com/9bOAaECMVd
初日の休憩時間中、現職の上司と同僚そして先に退職された先輩と同僚と一緒に撮っていただきました。
今日もSMSさんのシャトルバスで会場まで(ありがたや〜) #rubykaigi pic.twitter.com/Xp2euhbkb0
— しおい (Misaki Shioi) (@coe401_) 2022年9月8日
DAY2はわたしの登壇日でもありました。
#rubykaigiB にてこの後14:50よりお話しする「Packet analysis with mruby on Wireshark - dRuby as example 」の発表資料です。
— しおい (Misaki Shioi) (@coe401_) 2022年9月9日
This is a slide from my presentation at RubyKaigi 2022. よろしくお願いします!https://t.co/nCcF7QLqGI #rubykaigi
本番でお話しした「Packet analysis with mruby on Wireshark - dRuby as example」の資料はこちらです。
RubyKaigiの会場でお話しするのはこれが初めてだったために緊張で震え上がっていたのですが、何とか発表が始まりスライドを進めてちょうど中盤あたりに差し掛かったところで、何とフレッツ光の故障によるネットワーク障害が発生。
オンライン参加の方向けの中継が停止してしまい、わたしの発表はそこで一旦中断となりました。
中断中、不測の事態の発生にわたし自身は内心激しくアワアワしていたのですが、後でTwitterを見ると、会場にいた方にはその動揺っぷりはあまり伝わっていなかったようで安心しました。
また会場スタッフの方が舞台の裾に捌けるための準備をしてくださっている間に、観客席の方から
など続々と質問の声が上がり、それにわたしが答えるという思いがけないコールアンドレスポンス(????)が発生していました。
そのやりとりや、やりとりへの反応も含め、会場のMINSWANから温かく見守っていただいているのだな、と思うとじわじわ気持ちも落ち着いていきました。
その後一旦舞台の裾に捌けたものの、すぐにネットワークが回復する目処が立たなさそう、とのことでオンラインでの中継を中断したまま発表を再開。
このときにはだいぶリラックスできていたため、最後のデモまで無事に完走することができました。何なら普段の発表よりも良かったのでは。
(最終的に次の時間帯のセッションまでネットワーク回復せず…↓)
The network at the venue is still dead, and so currently running sessions "Caching With MessagePack" and "Create my own search engine." are not available online. We're recording all the talks, and the videos will soon be uploaded on YouTube. #rubykaigi
— RubyKaigi (@rubykaigi) 2022年9月9日
We diagnosed our fibre connection got broken. #rubykaigiA stream is now back using a wired link used as free Wi-Fi at the venue. #rubykaigi
— RubyKaigi (@rubykaigi) 2022年9月9日
オンライン参加の方には中断時点で発表が終わってしまった形になっており心苦しいのですが、後日アーカイブがYoutubeのRubyKaigiチャンネルにアップロードされるとのことなので、もしよければそちらで楽しんでいただけると幸いです。
(2022年11月4日追記: 動画が公開されました!)
またRubyKaigi運営チームの皆さん、あと会場スタッフの方がこうした事態に対応するために色々と手を尽くして下さっていたことに感謝しています。本当にお疲れ様でした。
発表終わりました!!
— しおい (Misaki Shioi) (@coe401_) 2022年9月9日
おいしい思いをさせていただきました & 途中お待ちくださったみなさんに感謝します!!!!
そして資料を公開しました!!!!(発表中Draftになっておりすみません🙏) https://t.co/jSJ4hSET4g
発表前にツイートで資料を案内するも、下書き状態だったという痛恨のミス。
発表後、沢山労いのお声をいただいたのもありがたかったのですが、それに加えて途中のトラブルのことだけではなく発表の内容そのものについても「この機能はこういう場面で使えそうかも」「ここはもっとこうするといいのでは」「これって〜ということ?」「面白かった」などなど感想や質問をいただけたのは本当に嬉しかったです。
今日も楽しかったー!!
— しおい (Misaki Shioi) (@coe401_) 2022年9月9日
わくわくするようなRubyの可能性を広げる話を沢山聴いて、会場の温かい雰囲気のおかげでわたしの発表も何とか終わり、Matzさんともお話できて、退職前の最後の機会に現職メンバーと津で結集することができました。
素晴らしいDAY2をありがとうございました!!!! #rubykaigi pic.twitter.com/hIIsaK7zFy
MatzさんにRubyとmrubyを作ってくださったことへの感謝を伝えることができました!
昨日の発表中、オンラインでご覧のみなさんには配信が止まったままだったということを失念しており、発表後の一連のツイートは思慮が足りていなかったなと一晩明けて反省しております…
— しおい (Misaki Shioi) (@coe401_) 2022年9月9日
後日アーカイブがアップロードされるとのことなので、もしよければ続きからお楽しみ頂けると幸いです! #rubykaigi
#rubykaigi 3日目もよろしくお願いします!! pic.twitter.com/UcmkpJT0d5
— しおい (Misaki Shioi) (@coe401_) 2022年9月10日
3日目にもなるとだいぶ体力の残量が減ってきているものの楽しすぎてテンション収まらず
RubyKaigi、ちょっと歩くと各所でおしゃべりが始まって楽しすぎる🥷
— しおい (Misaki Shioi) (@coe401_) 2022年9月10日
#rubykaigi 3日間おつかれさまでした!!!
— しおい (Misaki Shioi) (@coe401_) 2022年9月10日
めちゃめちゃ楽しかったです。
運営のみなさんありがとうございました!!また来年!!! pic.twitter.com/4h8rdITB7D
最後は松田さんのクロージングトークを聴き、思わず涙ぐみながら夢のような3日間を終えました。
来年はもっと安心して、人々がRubyKaigiに参加できるような世界になっていれば良いなと思います。
RubyKaigi 2023: May 11-13, 2023; See you in Matsumoto! #rubykaigi
— RubyKaigi (@rubykaigi) 2022年9月10日
松本で無事にお会いできますように!
その他に書き残しておきたいこと① 会場で聴いた発表について
今年も刺激を受けるトークが目白押しでした。個人的には
- kateinoigakukunさんの「Ruby meets WebAssembly」
- すごすぎる
- 技術的難易度の高い課題に対するアプローチの技術的難易度の高さよ…
- _ko1さんの「Making *MaNy* threads on Ruby」
- 難しかったけどMaNyのびしろは伝わってきました
- ユーザーがスケジューラを書かずに済むユーザーに優しい仕組みを提供しようと下さっているのかなと理解し、ありがたいなと思いました(素人感想)
- うなすけさんの「Do Pure Ruby Dream of Encrypted Binary Protocol?」
- ご苦労お見受けしました
- それでも一歩ずつQUIC実装のために前進されているのがすごいなあ
- m_sekiさんのCreate my own search engine.」
- hsbtさんの「Why is building the Ruby environment hard?」
- 自分のチーム内でも話題になったような事例から世界でまだ数人しか踏んでいないレア事例まで、さながらビルドエラーの展覧会のよう
- 「ソフトウェアは何もしないと壊れる」名言…
- nay3さんの「The Better RuboCop World to enjoy Ruby」
- 自分の中で初心者の気持ちとちょっと脱初心者した気持ちがせめぎ合って大変でした
- わたしの近くに座っていらした角谷さんとmoroさんが「そうなんだよなー」とうんうんされていたのが印象的でした
- ima1zumiさんの「String Meets Encoding」
- すごく丁寧に課題にアプローチされていて勉強になりました
- きっかけがすとうさんのツイートの読み間違えだった、というお話が良すぎる & 経済効果すごい!!
あたりが刺さっていますが、現地で聴けなかった気になるものもまだ沢山ある!!
その他に書き残しておきたいこと② #rubyfriends
わたしにとっての初めてのRubyKaigiは3年前、2019年に福岡で開催されたRubyKaigiで、当時の自分はまだ仕事を始めたばかり、Rubyコミュニティに顔を出し始めたばかりのプログラマ1年生でした。
その際も会場や懇親会の場で沢山の参加者の人々とお話できて感激していたのですが、それから3年経ち、今回のRubyKaigiではその時よりも更に更に、もっと沢山の人々と一緒にRubyKaigiを楽しむことができました。
この3年を過ごすうちに、自分はこんなに沢山の人々と交流し、あるいは新たに出会い、お世話になっていたのだな、と思うと何だか込み上げてくるものがありました。
今回会場で初めてお会いできた方、あるいは会場でお話しする機会がなかった方、そしてオンラインで参加をされていた方とも、来年のRubyKaigiもしくは別の場所でまたお会いできると嬉しいです。
その他に書き残しておきたいこと おまけ
自分の登壇の中断中、「いやー逆に緊張がほぐれてきました」などと口走っていた記憶があるのですが、実はその時が緊張のピークでした。嘘ついてすみません…
あまりの緊張に壇上で余計なことを言っていなかったか、今更ながらかなり心配しています。
プロを目指す人のためのRuby入門[改訂2版] (チェリー本) を読みました
11/29に発売されたプロを目指す人のためのRuby入門、通称チェリー本の第2版を著者の伊藤淳一@jnchitoさんからご恵送賜りました (ありがとうございます!)
遅くなりましたが、本書を読んだ感想を書かせていただきます。
まえがき: チェリー本とわたし
チェリー本といえば、第1版が発売されたのはちょうど4年前の2017年11月25日でした。
当時のわたしはプログラミングというものを学び始め、自分にとっての初めてのプログラミング言語であったRubyにも出会ったばかり。
タイミングの良いことにチェリー本の発売日とまったく同じ日、当時住んでいた福岡にて、地域RubyコミュニティFukuoka.rb主催の地域Ruby会議である福岡Ruby会議02が開催されていました。
右も左も分からない状態で福岡Ruby会議02に参加したわたしは、わからないなりにこのカンファレンスの空気に気持ちを昂らせ、そして昂った気持ちのその勢いで帰り道にチェリー本を購入したのでした。
そうして出会ったチェリー本をまずは一読し、まだまだ理解には及ばなかったために後日再読し、更にプログラマに転職してからもTama.rbのチェリー本輪読会でも今一度再読し、あと別の機会にももう一回読み直した記憶があるような…もちろん通読するばかりでなく、働き始めてしばらくの間は辞書代わりに手元に置いて、必要な局面が訪れるたびに開いていました。
チェリー本を読んでプロ (グラマ) になった人は沢山いると思います。わたしもそのうちの一人です。
そうやってお世話になってきたチェリー本の第2版を、今度は職業Rubyプログラマの立場で読むことができ、とても嬉しく思っています。
改めてありがとうございます! > 伊藤さん
チェリー本はどんな本?
…についてはすでに公式・非公式問わず、たくさんの紹介があります。
おしゃれな公式ページ ruby-book.jnito.com
出版社による紹介ページとサポートページ
著者の伊藤さんご自身による紹介記事 blog.jnito.com
また、第1版との比較については、@aim2bpgさんのブログにて (伊藤さんも驚かれるほど) 詳細に解説されていました。
こ、これは……(驚愕)。僕が改訂2版でどんな加筆修正をやったのか、ほぼ全部解明されてしまっている!!こんな短期間でここまで分析できるのは凄すぎです。どうもありがとうございます!!😭 / “【書評】🍒「プロを目指す人のためのRuby入門[改訂2版]」を第1版と読み比…” https://t.co/AGDCDwha4y
— Junichi Ito (伊藤淳一) (@jnchito) 2021年12月11日
感想
さすがに最近はチェリー本にお世話になる機会が減っていたので久々に通読したことになります。
本文中で紹介されている構文やメソッドのうち多くは普段から馴染みがあるものなので、自然と以前読んでいまいちピンと来なかったところや、以前は頭に入りきらなかったところに意識が向くことになります。
そうすると、まるで復習をしているように「そうそう、これってこういうこと!」と現在の自分の理解を確かめる場面があったり、あるいは全くの新しい発見に出くわす場面があったり、4年前とはまた違う新鮮さを覚えながら読み進めることができました。
例えば、「2.12.3 式(Expression)と文(Statement)」(P74)
ここでは式と文の違いを「値を返し、結果を変数に代入できるものが式」「値を返さず、変数に代入しようとすると構文エラーになるものが文」と定義します。 このような分類で指揮と文を区別すると、Rubyのif文やメソッド定義は文ではなく、式になっています。なぜならif文やメソッド定義が値を返すからです。
について、「メソッド定義が値を返す」ことについては今回読んでいて初めてちゃんと認識しました。
(REPL環境でメソッドを定義するとメソッド名がシンボルで返ってくるので、言われてみればそれはそう…!という感じなのですが)
解説そのものが第1版よりもさらに丁寧にわかりやすいよう改善されていることも大きいと思います。
特に以前読んだ時に難しく感じた第10章「yieldとProcを理解する」は、処理順が図示されていたり、そもそものyieldやProcの用途について踏み込んだコラムが追加されており、これなら初めて読む人でもyieldとProcの概要を掴むことができるのではないかなと思いました。
もちろん復習だけでなく、新しい解説も追加されています。
第11章「パターンマッチを理解する」では、パターンマッチの作者である@k_tsjさんをして「世界トップレベルと言っていい」と評されるほど丁寧な、具体例を交えた解説がなされています。
チェリー本こと「プロを目指す人のためのRuby入門」の改訂版発売に当たりレビュアーとしてお手伝いさせていただきました。多岐に渡ってアップデートがある本書ですが、特にパターンマッチについては丸々一章を割いて世界トップレベルと言っていい詳細な解説が行われています。https://t.co/YWQz6qwXGB
— k_tsj (@k_tsj) 2021年12月11日
自分自身ではまだ本格的にパターンマッチを活用する機会を得ていないのですが、サンプルコードを動かし演習をするだけでもその気持ち良さを試すことができます。
使いどころがあればぜひ使いたい!…し、その機会が来たときにはまたもやチェリー本を傍らに実装を検討することになりそうな気がしています。
新機能といえば他にも第12章「Rubyのデバッグ技法を身につける」では、もうすぐリリースのRuby3.1から導入される新しいデバッガ debug.gem の基本的な使い方が紹介されています。
debug.gemは非常に多機能で、公式のREADME.mdもとてもとても充実しているのですが、とりあえずチェリー本で紹介されている機能だけでも頭に入れておけば迷わずスッと使い始めることができそうです。
更に第13章「Rubyに関するその他のトピック」の中には、typeprofとsteepの概要と使い方について、型入門者向けの絶妙な塩梅での解説が含まれていたりします。
個人的にチェリー本の一番の特徴は、その網羅性と実用性にあると思います。
だからこそ、第1版を読んでいた当時から時間をおいて今、改めて第2版を読むことによって、この4年間の総復習と新機能についての実務を前提にしたキャッチアップをすることができるのではないかなと感じました。
最後に
Rubyプログラマとして働いている今、チェリー本はプロを目指す人々のためだけの本ではないなあ、と思っています。
チェリー本 第2版を読み、自分のこれまでを振り返り、今現在とこれから将来のRubyとのお付き合いを考える時間を持つことができました。
特にわたしと同じく第1版を読んでプロ (グラマ) になった皆さん、年末年始休暇のお供にいかがでしょう?
Ruby Advent Calendar 2021: パケットキャプチャ入門 with dRuby
訂正とお詫び (2022/3/5)
この記事の最後に「WiresharkがdRubyに対応していないためキャプチャできなかった」と結論づけているのですが、筆者の不見識でWiresharkにdRuby用のディセクタがビルトインされていることに気づいていませんでした。
申し訳ありません。
以下のように設定するとdRubyパケットをキャプチャすることが可能です。
Wireshark > Preferences > Protocols > DRb
ポート番号を指定する
以下は元の記事 (未編集) です↓
Ruby Advent Calendar 2021 17日目の記事です。
昨日は@okuramasafumiさんでした。
この記事は
2台の機器 (MacBookとThinkPad) がお互いに通信を行うような
dRubyスクリプトを書き、その実際の通信の様子をWiresharkで眺める
という小さな実験を行った際の記録です。
きっかけ
最近Wiresharkに入門したのですが、それと同時にdRubyにも興味が湧いて勉強していました。
ご存知dRubyは、ネットワーク越しにRubyオブジェクトを操作することができるフレームワークです。
HTTP通信と同じく、dRubyスクリプトを実行するときに機器間で実際に発生する通信は通常、TCP/IPプロトコルレイヤによって隠蔽されています
そこで機器間で送受信されたdRubyスクリプトが実際にパケットとして、あるいはアプリケーションデータ (※) としてネットワーク上をどんな風に流れているのか、その様子を見てみたいと思い立ち、今回の実験に至りました。
※ 実際にキャプチャした結果衝撃の事実に直面することになりました。むしろなぜこの時点で気づかなかった…
以下記事の内容に誤りなど技術的指摘がありましたら、お手数ですが教えてください。
動作環境
- Ruby 3.0.2 (dRuby 2.0.4)
- Wireshark 3.4.9 (macOS Intel 64-bit)
- MacBook (macOS 11.6) と ThinkPad (Ubuntu18.04) をそれぞれ自宅のWiFiネットワークに接続。
2台のPCのグローバルIPアドレスを調べたところ、
となっていました。
2台の機器は以下のように疎通確認済みです。
# ThinkPad $ ping6 2400: ... :4808 -c 3 PING6(56=40+8+8 bytes) 2400: ... :439c --> 2400: ... :4808 16bytes from 2400: ... :439c, icmp_seq=0 ttl=64 time=4.26ms 16bytes from 2400: ... :439c, icmp_seq=1 ttl=64 time=4.86ms 16bytes from 2400: ... :439c, icmp_seq=2 ttl=64 time=4.25ms --- 2400: ... :439c439c ping6 statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss
# MacBook $ ping6 2400: ... :439c -c 3 PING6(56=40+8+8 bytes) 2400: ... :4808--> 2400: ... :439c 16bytes from 2400: ... :4808, icmp_seq=0 hlim=64 time=94.183ms 16bytes from 2400: ... :4808, icmp_seq=1 hlim=64 time=116.538ms 16bytes from 2400: ... :4808, icmp_seq=2 hlim=64 time=34.263ms --- 2400: ... :4808 ping6 statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss
※ MacからThinkPadへの通信にやたら時間がかかっていますが、弊環境だと大体いつもThinkPadの方が通信速度が優秀なのです…
改めてdRubyについて
皆さんご存知、Rubyのための分散オブジェクトシステムです。
分散オブジェクト技術 【distributed object technology】
library drb
dRubyによって、Rubyオブジェクトをプロセスやネットワークを超えて操作することが可能になります。
作者である咳さんご自身がdRubyの基本的な使い方について紹介されているRubyKaigi 2016の登壇動画はこちらです。
簡単な動作例を以下に示します。
ターミナルを二つ開いてそれぞれirbを起動し、drbライブラリをrequire
します。
# ターミナル1 $ irb --simple-prompt >> require 'drb' => true
# ターミナル2 $ irb --simple-prompt >> require 'drb' => true
続いてターミナル1でFoo
クラスとインスタンスメソッドfrom
を定義します。
# ターミナル1 ?> class Foo ?> def from ?> "I'm from terminal 1!" ?> end >> end => :from
続いてターミナル1でDRb.start_service
を実行すると、サーバープロセスを起動することができます。
このとき、DRb.start_service
の第一引数にクライアントがアクセスするためのURI、第二引数にFoo
オブジェクトを渡します。
第二引数に渡したFoo
オブジェクトは他のプロセスから操作可能なオブジェクトとして公開されます。
# ターミナル1 >> foo = Foo.new >> puts foo #<Foo:0x00007f81149b7cf0> >> DRb.start_service("druby://localhost:8080", foo) # ローカルホストのポート番号8080で待ち受ける
これで、ターミナル2からターミナル1のFoo
オブジェクトに対してメソッド呼び出しができるようになります。
ターミナル2からFoo
オブジェクトに対してメソッド呼び出しするためには、まずターミナル2でDRbObject.new_with_uri
を実行します。
このとき、引数にターミナル1のサーバープロセスが待ち受けているURIを指定します。
# ターミナル2 >> foo = DRbObject.new_with_uri('druby://localhost:8080') >> puts foo #<Foo:0x00007f81149b7cf0>
こうすることによってターミナル2からターミナル1のFoo
オブジェクトの複製であるオブジェクト (※) を取得することができます。
※ この辺り難しいので詳しくは後述のdRuby Bookを参照
ターミナル2から変数foo
に格納されたオブジェクトに対してfrom
メソッドを実行すると…
# ターミナル2 >> foo.from => "I'm from terminal 1!"
ターミナル2にfrom
メソッドの返り値が表示されました!
ターミナル2から、ターミナル1で定義したFoo#from
のメソッド呼び出しに成功したということです。
逆に、ターミナル1からターミナル2にあるオブジェクトへの操作も試してみましょう。
# ターミナル2 ?> class Bar ?> def from ?> "I'm from terminal 2!" ?> end >> end => :from >> DRb.start_service("druby://localhost:8081", Bar.new) # ローカルホストのポート番号8081で待ち受ける
# ターミナル1 bar = DRbObject.new_with_uri('druby://localhost:8081') bar.from => "I'm from terminal 2!"
こちらももちろん成功します。楽しいですね!
ちなみにBar#from
の内容を"I'm from terminal 2!"
ではなくputs "I'm from terminal 2!"
にしたりすると、ターミナル2に"I'm from terminal 2!"
が表示され (ターミナル2の標準出力はターミナル2のままなので) 、ターミナル1にはnil
が返ります (puts
の返り値はnil
なので) 。
他にもdRubyは様々な特徴を備えています。
詳しくはdRubyによる分散・Webプログラミング(あるいは英語版・無料のThe dRuby Book)、そして「令和のdRuby Book」といった趣きのn月刊ラムダノート Vol.2, No.1(2020)の特集「#2 dRubyで楽しむ分散オブジェクト」もおすすめです。
ThinkPadとMacBook、それぞれの機器で実行するdRubyスクリプト
今回の実験では、次のようなプログラムを動作させることにしました。
- ThinkPadはサーバープロセスをポート番号8080で起動し、MacBookからアクセスすることができる空のKVS
{ }
(…という名の空ハッシュ)を公開する - MacBookはサーバープロセスをポート番号8081で起動し、ThinkPadからアクセスできるようにしておく
- MacBookがThinkPadの公開しているKVS
{ }
を取得する - MacBookが取得したKVSにレコード
{ "greeting" => "Hello from MacBook" }
を追加する - ThinkPadは自身が公開しているKVSにレコードが追加されたことを検知し、自身の標準出力にログを出力する
- MacBookが再びKVSにレコード
{ "stdout" => $stdout }
を追加する - ThinkPadは再び自身が公開しているKVSにレコードが追加されたことを検知し、自身の標準出力にログを出力する
- ThinkPadはKVSに追加されたレコードがttyに結合している場合、結合先にメッセージ
"Hello from ThinkPad"
を出力する
プログラムは次のようになります。
https://github.com/shioimm/til/tree/master/activities/learning_network_with_drbgithub.com
# thinkpad.rb require 'drb' kvs = {} # 新たに追加されたレコードを検証するために使用する last_kvs = {} # サーバープロセスをポート番号8080で起動して空のKVSを公開 DRb.start_service("druby://#{ENV['LOCAL_HOST_ADDRESS']}:8080", kvs) puts "Start server process on #{DRb.uri}" loop do if kvs.size > last_kvs.size puts "New record has been added:\n#{kvs}" new_values = (kvs.values - last_kvs.values) new_stdouts = new_values.select { |value| value.respond_to?(:tty?) && value.tty? } unless new_stdouts.empty? # 追加されたレコードがttyに結合している場合は"Hello from ThinkPad"を出力 puts "Greet to client: 'Hello from ThinkPad'" new_stdouts.each { |new_stdout| new_stdout.puts "Hello from ThinkPad" } end last_kvs = kvs.dup end sleep 1 end
# macbook.rb require "drb" # サーバープロセスをポート番号8081で起動 DRb.start_service("druby://#{ENV['LOCAL_HOST_ADDRESS']}:8081") puts "Start server process on #{DRb.uri}" # ThinkPadが公開しているKVSを取得 uri = "druby://#{ENV["REMOTE_HOST_ADDRESS"]}:8080" kvs = DRbObject.new_with_uri(uri) puts "[LOG] uri = #{uri}" puts "[LOG] kvs = DRbObject.new_with_uri(uri)" puts "[LOG] kvs:\n#{kvs}" # KVSにレコード { kvs["greeting"] => "Hello from MacBook" } を追加 kvs["greeting"] = "Hello from MacBook" puts "[LOG] kvs['greeting'] = 'Hello from MacBook'" puts "[LOG] kvs:\n#{kvs}" sleep 1 # KVSにレコード { kvs["stdout"] => $stdout } を追加 # この$stdoutはMacBook自身の標準出力 kvs["stdout"] = $stdout puts "[LOG] kvs['stdout'] = $stdout" puts "[LOG] kvs:\n#{kvs}" puts "[LOG] sleep"; sleep
あらかじめ環境変数LOCAL_HOST_ADDRESS
とREMOTE_HOST_ADDRESS
を各機器にセットしておきました。
ThinkPadのLOCAL_HOST_ADDRESS
はThinkPadのIPアドレス (末尾439c
)、REMOTE_HOST_ADDRESS
はMacBookのIPアドレス (末尾4808
) です。
MacBookにはその逆になります。
これらのプログラムをそれぞれMacBookとThinkPadに置き、それぞれ実行すると以下のようになります。
# ThinkPad $ ruby thinkpad.rb Start server process on druby://2400: ... :439c:8080
# MacBook $ ruby macbook.rb Start server process on druby://2400: ... :4808:8081 [LOG] uri = druby://2400: ... :439c:8080 [LOG] kvs = DRbObject.new_with_uri(uri) [LOG] kvs: {} [LOG] kvs['greeting'] = 'Hello from MacBook' [LOG] kvs: {"greeting"=>"Hello from MacBook"}
# ThinkPad ... New record has been added: {"greeting"=>"Hello from MacBook"}
# MacBook ... [LOG] kvs['stdout'] = $stdout [LOG] kvs: {"greeting"=>"Hello from MacBook", "stdout"=>#<DRb::DRbObject:0x00007fa55c8a57b0 @uri="druby://2400: ... :4808:8081", @ref=80>} [LOG] sleep
# ThinkPad ... New record has been added: {"greeting"=>"Hello from MacBook", "stdout"=>#<DRb::DRbObject:0x00007fa55c8a57b0 @uri="druby://2400: ... :4808:8081", @ref=80>}
# MacBook ... Hello from ThinkPad
無事にMacBookからThinkpadへ、ThinkPadからMacBookへ、お互い通信を行うことができました!
実際の通信の様子をWiresharkでキャプチャしてみる
上記のやりとりをキャプチャします。
WiresharkはこちらからMacBookへダウンロードし、インストール済みです。
(ThinkPad(Ubuntu)にもapt
を使ってインストールしたのですが、今回はクライアントであるMacBookでキャプチャしたファイルのみを確認します)
早速Wiresharkを開いてキャプチャを開始すると、次のような通信の様子が表示されました。
この状態で、それぞれの機器でプログラムを実行します。
# ThinkPad $ ruby thinkpad.rb Start server process on druby://2400: ... :439c:8080 New record has been added: {"greeting"=>"Hello from MacBook"} New record has been added: {"greeting"=>"Hello from MacBook", "stdout"=>#<DRb::DRbObject:0x00007fa55c8a57b0 @uri="druby://2400: ... :4808:8081", @ref=80>}
# MacBook $ ruby macbook.rb Start server process on druby://2400: ... :4808:8081 [LOG] uri = druby://2400: ... :439c:8080 [LOG] kvs = DRbObject.new_with_uri(uri) [LOG] kvs: {} [LOG] kvs['greeting'] = 'Hello from MacBook' [LOG] kvs: {"greeting"=>"Hello from MacBook"} [LOG] kvs['stdout'] = $stdout [LOG] kvs: {"greeting"=>"Hello from MacBook", "stdout"=>#<DRb::DRbObject:0x00007fa55c8a57b0 @uri="druby://2400: ... :4808:8081", @ref=80>} [LOG] sleep Hello from ThinkPad
プログラムの実行に成功したため、一旦ここでキャプチャを止めてファイルとして保存しました。
保存したファイルを開き、今回実験した内容を通信に絞り込むため次のような条件でフィルタをかけました。
tcp.port == 8080 || tcp.port == 8081
すると…
(上から下まで全部TCP)
(dRubyスクリプトが含まれているはずの) アプリケーションデータがキャプチャできていない…!?
…と、ここまで来て気づいたのですがWiresharkがキャプチャできるのはWireshark自身がサポートしているアプリケーションプロトコルのみなのでした。
残念ながらその中にdRubyは含まれていないため、キャプチャファイルではトランスポート層でやりとりしたTCPパケットの情報のみが表示されています。それはそう…!!
せっかくなので、dRubyならではのちょっと特徴的なパケットの様子を見てみたいと思います。
先ほど実験用プログラムの中で、ThinkPadのサーバープロセスのポート番号を8080、MacBookのサーバープロセスのポート番号を8081としました。
通信の始まりであるこの行では、ThinkPadの8080番に対して、MacBookの55094番から[SYN]を送るところから通信が始まっています。
この時、MacBookはクライアントとしてパケットを送信しているため、自身のサーバーのプロセスの8081番ではなくてエフェメラルポートである55094番を使用しています。
2行目ではThinkPadの8080番からMacBookの55094番に対して[ACK]が返っていることが確認できます。
この後順調に通信が進んでいくのですが、190行目で突然シーケンス番号0の新しい通信が開始されます。
見切れていますが送信元のIPアドレスの末尾が439c
、宛先のIPアドレスの末尾が4808
でポート番号が8081になっているので、これはThinkPadからMacBookのサーバーポート宛の通信であることがわかります。
(ThinkPadからMacBookへ"Hello from ThinkPad!"
と送信している分です)
今度はThinkPadがクライアントになっているので、送信元のポート番号として38272という番号が割り当てられています。
最後に、それぞれの端末から通信をCtrl+Cで切断した部分がこちらです。
シンプルなサーバー・クライアントシステムの場合、お互いが[FIN, ACK]と[ACK]を送り合っておしまいになると思うのですが、今回サーバープロセスとクライアントプロセスが2つずつあるため、通常の2倍の[FIN, ACK]と[ACK]が飛び交っていてちょっと面白いです。
まとめ
今回の実験の内容自体はdRuby的にもWireshark的にも最初の一歩を踏んだ程度のものではあるのですが、個人的にはパケットをキャプチャしてまじまじ眺める経験そのものが初めてだったためとても勉強になりました。
残念ながら送受信しているdRubyスクリプトそのものをアプリケーションデータとして確認することはできませんでした…が、実際にネットワークを超えて行くTCPパケットとしてのdRubyの姿を眺めることができて感動しました。
WiresharkもdRubyもまだまだ奥が深そうなので、引き続き楽しんでいきたいと思います。
以上、「Ruby Advent Calendar 2021: パケットキャプチャ入門 with dRuby」でした。
明日は@yancyaさんです。
それでは皆さん楽しいクリスマスをお過ごしください🎄🍰
Rubyist近況 Advent Calendar 2021: 近況報告 + 今年一番お世話になったメソッドにお礼を言いたい
Rubyist近況 Advent Calendar 2021 12日目の記事です。
昨日は@miyohideさんのRubyもJavaも楽しく学ぶ でした。
近況ということで2021年を振り返ってみたいと思います。
仕事
現職で働き始めて3年が経ちました。
変わらず英語塾で学習管理システムのバックエンド開発を担当しています。
昨年 (2020年) 達人プログラマー、エクストリームプログラミング、Clean Agileと立て続けに素晴らしい書籍を読んだため、この経験を仕事で活かせないかな〜と思い今年からカリキュラムチームの定例ミーティングに参加させてもらうようになりました。
より現場に近いカリキュラムチームと一緒に仕事をするようになったことで、(今更ですが) システムだけではなくお客様に提供するサービス全体を自分 (たち) の作るプロダクトとして考えることができるようになった、というのが自分にとっての今年一番大きな進歩ではなかったかなと振り返っています。
開発の進め方にも自分の中に軸のようなものが生まれたように思います。
また、ちょうど一年くらい前に開発チームメンバーが3人増えて賑やかになりました。
一方ご時世柄もあり全員リモート勤務なので、お互いが何をやっているのかわからない状況が発生しないよう、メンバーや上司の発案で毎日雑談タイムを設けたり、毎週技術書の読書会をしたり、週次で皆の動きを振り返ったりしています。
ただコミュニケーションの方法は人それぞれだし、そもそも自分自身もあまり得意な方ではないので、今より更に良くできる余地はありそう。
とはいえ、一緒に働く人たちと上司がいつも本当にniceなおかげで楽しく仕事しています。
前述のカリキュラムチームも含め、周りの人々からは引き続き学ぶことばかりです。
今現在はこれからのサービス展開に向け、これまで経験した中でも一番大がかりな仕事の真っ最中です。
これはまだしばらくかかりそうなので、来年も引き続きがんばります。
仕事以外
憧れのRubyKaigiに登壇しました!!!!
というのが今年一番大きな出来事です。
詳しくは↑の記事に書いたので、ここではそれ以外のことを…
- 3月、Fukuoka.rb 200回 LT大会 (#202)で喋りました
- 資料
- スレッドプログラミングについて勉強しており、ruby-jpでJava言語で学ぶデザインパターン入門 マルチスレッド編という本をお勧めしてもらったのがきっかけでした
- 2~4月くらい、プログラミングElixirをお供にElixirの勉強をしていましたが、わたしにはまだ早すぎた感がありました
- ただ、おかげでRubyのパターンマッチにちょっと親近感が湧きました
- なお、プログラミングElixirはまえがきとあとがきも最高でした…
- 4月、1月から読み始めたLinuxプログラミングインターフェース(1604ページ)を読み終えました
- これを読んで何かを作ろうという段階ではないのですが、困ったらとりあえずこの本、というお守り代わりにしようと思っています
- 2021年の目標は「LPIを読む」だったので達成できて嬉しいです
- しばらく趣味の喫茶店を控え目にしていたのですが4月、感染状況の様子を伺いつつ銀座のカフェ・ド・ランブルに行きました
- Asakusa.rbでおすすめしてもらいました
- 5月、キッズドアのマンスリーサポーターになりました
- わたしは自分自身が子育てに関わっていないので、自分の周りの親御さんたちの奮闘を (主にTwitterで) 陰ながら応援するくらいしかできないのですが、その分世の中のお子さんたちへ、わずかながらでも自分にできることができたらいいなと密かに思っています
- 5~6月、マスタリングTCP/IP 入門編を読み直したら学びしかなくてびっくりしました
- 6~9月、RubyKaigiの準備で記憶がない…
- 9月以降はRubyKaigiの余韻にひたりつつdRubyに入門していました
- The dRuby Book、n月刊ラムダノート Vol.2, No.1(2020)、過去のRubyKaigiでの咳さんの動画などなど
- プロセス (ネットワーク) のこちら側にいるRubyオブジェクトと向こう側にいるRubyオブジェクト同士で互いにメッセージを送受信するのが個人的にぐっときます
- dRubyについては12/17更新のRuby Advent Calendarでもう少しだけ書きます
- 10月、2019年から運営として関わっていたTama.rbが最終回を迎えました
- 寂しいけれどこれもまた一つ節目かなという気がします
- なお、Tama.rb内でわたしが立ち上げて今は@okuramasafumiさんが運営してくださっているOSSコードリーディング部改めrubygemsコードリーディング部は引き続きやっていきます
- 明日12/13第2回をやります Rackを読む - connpass
- さらに10月、Kaigi on Rails 2021に一参加者として参加しました (重言)
- 10月以降、感染状況が少し落ち着いているので、今のうちということで週末に趣味の喫茶店に出かけたりしています
- 出かけた先の街をぶらぶら散歩するのが最近の趣味です。川にも行きました
- 気づいたら上京して3年を超えていましたが、半分自粛生活だったので全然実感がなく、いまだにどこに行ってもおのぼりさん状態です
- 11月、大江戸Ruby会議09 出前Editionにこれまだ一参加者として参加しました (重言2)
- 最っっっ高のイベントでしたね
- Asakusa.rb 第634回 (キリ番) ミートアップ開催おめでとうございます
- 12月、Ruby3.1リリースを前に話題のRuby関連技術書(研鑽Rubyプログラミング β版、プロを目指す人のためのRuby入門[改訂2版])が2冊も出版され、それぞれ楽しく読んでいます
- 方向性の異なる二冊を同時に読むと何もわからなくなります
- 今年いつの間にかFukuoka.rbのconnpassページの管理者に追加してもらっていました
- Fukuoka.rb 第234回 (キリ番) ミートアップ開催おめでとうございます
- 今年 (も) 上記した本含めてたくさん本を読みました。そのうち多くの本を周りのRubyistの人々におすすめしていただきました
- 今年も相変わらずAsakusa.rbとFukuoka.rbによくいました。他の地域Rubyコミュニティミートアップにもたまにいます
ということであっという間に思えて実は色々あった今年も相変わらずRubyでお仕事をし、Rubyコミュニティにいて、Rubyが好きです。
RubyとRubyistの人々には2021年もたくさんお世話になりました。
プログラマとして過ごす生活の中で自分が本当に好きだなと思える言語や言語コミュニティがあるというのは幸せなことだなと思います。
そんな訳でせっかくなので、今年自分が書いたRubyプログラムの中で一番お世話になったメソッドにお礼を言うことにしました。
といっても、業務も含めて実際に書いたコード全てを集計して一番お世話になったメソッドを見つけるのはさすがに大変です。
わたしは毎日「その日新しく知ったこと」をtilというリポジトリにまとめているのですが、この中には練習のために書いてみたコードや写経したコード、イベントのために書いたコードなども入っています。
なので今回はこのtilリポジトリ内のコードを対象に集計することしました。
要件は次の通りです。
- 今年初め(1月1日)からこの日記を書いた12月3日までの間に更新されたファイルを対象に、各ファイル内で実行されているメソッドごとの実行回数を集計する
- その中でも特にお世話になった (リポジトリの中で実行回数が多かった) メソッドを20個、降順に取得する
- 明示的にソースコード中で呼び出したメソッドだけではなく、Ruby自身がコードの裏側で実行しているメソッドも対象に含める
ただし、そのままでは実行が難しかったものがあったのでいくつか条件をつけました。
- 無限ループが含まれるコードがあるため、実行時間が5秒以上かかったファイルは例外を上げて次の処理に移る
- 特定の条件付きで実行することを想定して書かれているコードがあるため、実行時に例外が発生した場合は例外を上げて次の処理に移る
集計のために書いたスクリプトは以下の通りです。
til/counter.rb at master · shioimm/til · GitHub
require 'timeout' files = ARGV counter = Hash.new { 0 } trace = TracePoint.new(:call, :c_call) { |tp| counter["#{tp.method_id} (#{tp.defined_class})"] += 1 } $stdout = File.open(File::NULL, 'w') # ファイル実行中の出力を抑制する files.each do |file| f = File.open(file, 'r') begin Timeout.timeout(5) { trace.enable { eval f.read } } rescue StandardError, LoadError end f.close end $stdout = STDOUT # 出力を元に戻す most_used_methods_20 = counter.sort_by { |_method, count| count }.reverse.first(20) pp most_used_methods_20.to_h
(もっと良い方法があるかもしれないので、識者の方に突っ込みをいただきたいです…)
取得したメソッドのうち、一番お世話になったメソッドには次の通りお礼を言います。
# ... puts "#{most_used_methods_20[0][0]}、本年は大変お世話になりました。\n来年もよろしくお願いします。"
早速実行してみました。
$ find ~/til -name *.rb -newermt '20210101' | xargs ruby ~/til/activities/20211212_rubyist_advent_calender/counter.rb
すると、次のように結果が出ました。
{"+ (Integer)"=>3131838, "up (Counter)"=>40000, "synchronize (Thread::Mutex)"=>21471, "method_added (Module)"=>3054, "-@ (String)"=>2560, "initialize (Thread)"=>2046, "new (#<Class:Thread>)"=>2046, "sleep (Kernel)"=>1775, "wait (Thread::ConditionVariable)"=>1767, "sleep (Thread::Mutex)"=>1767, "data (Gem::StubSpecification)"=>1468, "file? (#<Class:File>)"=>1372, "% (String)"=>1316, "chr (Integer)"=>1312, "+ (String)"=>1260, "to_s (Symbol)"=>1182, "rand (Kernel)"=>1068, "write (IO)"=>970, "=== (Module)"=>895, "current (#<Class:Thread>)"=>871}
ということで、2021年わたしが一番お世話になったメソッドはIntegerの+
でした!
おそらくこのファイルの実行によって数が増えたものと思われます。
https://github.com/shioimm/til/blob/master/practices/ruby/concurrency/benchmarks/20210131_bench.rb
その他のメソッドについても、今年前半に勉強していたスレッドプログラミング関連のものが多そうです。
ベンチマーク用スクリプトの中で使用していたメソッドなのでだいぶチート感がありますが、お世話になったことに変わりはないので+
には早速お礼を言いました。
+ (Integer)、本年は大変お世話になりました。 来年もよろしくお願いします。
以上、「Rubyist近況 Advent Calendar 2021: 近況報告 + 今年一番お世話になったメソッドにお礼を言いたい」でした。
明日は@s01さんです。
それでは皆さん楽しいクリスマスをお過ごしください🎄🍰
RubyKaigi Takeout 2021に登壇しました
しおいです。
9/9-9/11に開催されたRubyKaigi Takeout 2021 DAY1にて登壇しました。
RubyKaigiはわたしにとって憧れのテックカンファレンスであり、Rubyと出会った当時からいつか登壇したいと願ってきたため、ありがたいことに今年その機会に恵まれてとても感慨深く思っています。
この記事ではプロポーザルを出すに至ったきっかけからRubyKaigi Takeout 2021本編登壇、そして後日開催されたFukuoka.rbでの感想戦参加までを振り返ります。
プロポーザル提出まで
前述の通りRubyKaigiはわたしにとって憧れであり、遠い雲の上のような存在でした。
そのためCFPがオープンされた当初はプロポーザルを出す予定はなく、今年は無理だけどいつかは出せたら良いなあ、などと考えながら、プロポーザルを出そうと準備されている他の人々を応援しながら過ごしていました。
風向きが変わったのは、Twitter上でRubyKaigiのチーフオーガナイザーであるamatsudaさんからこんなリプライを頂いたあたりからです。
RubyKaigiのような最高すぎるイベントが存在してたり存続してたりするのは割と偶然みたいな感じなので、その「いつか将来」の時点でRubyKaigiがまだ奇跡的に続いてる保証はどこにもないのですよ。というか、続いてないだろうと思っといたほうが良いぐらいです。
— Akira Matsuda (@a_matsuda) 2021年6月10日
そんなわけで、いつか将来、何かを作ったけどプロポーザルを未来永劫出しそびれてたことを悟って後悔する可能性は大いにあり得るとして、プロポーザルを早く出しすぎて後悔することってあり得ると思いますか?
— Akira Matsuda (@a_matsuda) 2021年6月10日
いや、ない(反語)。
(※ちなみにこのリプライの元ツイートでわたしが思いを馳せている「プロポーザル」は、もう少し先の日程で開催されるKaigi on Railsに対するものだったのですが、結果的にはRubyKaigiの方に集中することになりKaigi on Railsの方にはプロポーザルを出せずじまいでした…)
この時点では出すネタがまったく思いつかず、色々考え込んで無駄に落ち込んだりしていたのですが、その次に参加したAsakusa.rbのミートアップで人々から熱い熱いエールを頂き、さらにその後参加したFukuoka.rb主催のランチ会Nishitetsu.rbで人々から更にその5倍濃縮くらいの濃い濃いエールを頂き、いよいよ開き直ってプロポーザルを出す覚悟を決めました。
今日の西鉄.rb( #fukuokarb )でうづらさん、 #asakusarb で松田さんからそれぞれ「プロポーザルを出すとステージが変わる」とアドバイスを頂いたので、ネタがまとまるかどうかは一旦置いておいて、今年のRubyKaigiにプロポーザルを出せないかあと一週間案を練ってみようと思います。ひえー。
— しおい (Misaki Shioi) (@coe401_) 2021年6月22日
※余談ですが、同じくNishitetsu.rbに参加されてこの時のすったもんだやりとりを見ていたima1zumiさんはスッとプロポーザルを提出され、ススッと登壇を決めて当日(DAY 3)格好良い発表をされていたのでした。
※そしてNishitetu.rbの主催者であり、RubyKaigi登壇常連であるudzuraさんも圧巻の発表。
※Nishitetu.rbすごいな
プロポーザルの提出期限は6/30、この時すでに6/22、覚悟は決まったもののネタは無いのでまずはネタを絞り出す必要がありました。
自分自身がここしばらく心を寄せているネットワークプロトコル関連で何か喋りたいと思い、いくつか案を出しました。
- HTTP/2クライアントをRubyで自作する(自分自身が知識不足な上、格好良い先行gemが既にたくさんあるのでいまいち)
- TCPの上に自作のアプリケーションプロトコルをRubyで作る(ちょっと小ネタすぎる)
- TCPとHTTPの間に自作のアプリケーションプロトコルを追加できるフレームワーク(???)をRubyで作る(?????)
あまり意味はわからないですが、独創性、実装可能性、あとちょっと楽しそう(自分が)、という観点から3
をやってみることに決めました(6/25)
ざっと動くプロトタイプを作り(6/26)、頭を捻りながらプロポーザルを作文し、英語に直して何とか無事に提出することができました(6/27)。開き直ればやればできる。
RubyKaigiのプロポーザルを提出した!
— しおい (Misaki Shioi) (@coe401_) 2021年6月27日
まだ実装は全然終わっていないのでがんばる!! pic.twitter.com/PALwWmsmdx
Toycolの実装
この「TCPとHTTPの間に自作のアプリケーションプロトコルを追加できるフレームワーク」を使って自作したプロトコルを使うと、次のようにネットワーク通信を行うことができます。
登場人物は
- 自作プロトコル対応クライアント
- 自作プロトコルによるリクエストメッセージ
- 自作プロトコル対応サーバー
- アプリケーションサーバー
- Webアプリケーション
です。
通信の流れは
自作プロトコル対応クライアントから自作プロトコル対応サーバーへ 自作プロトコルによるリクエストメッセージを送る ↓ 自作プロトコル対応サーバーが自作プロトコルによるリクエストメッセージを HTTPフォーマットのリクエストメッセージへ変換する ↓ 自作プロトコル対応サーバーがアプリケーションサーバーへ HTTPフォーマットのリクエストメッセージを送る ↓ アプリケーションサーバーがWebアプリケーションを実行する ↓ アプリケーションサーバーから自作プロトコル対応サーバーへ HTTPフォーマットのレスポンスを送る ↓ 自作プロトコル対応サーバーが自作プロトコル対応クライアントへ HTTPフォーマットのレスポンスを送る
のようになります。
例えば、「あひるの鳴き声によって動作するDuckプロトコル」はこんな感じです。
1.まずはサーバーを立ち上げます
(config_duck.ru
という名前のアプリケーションファイルを用意しています)
サーバー側
$ toycol server config_duck.ru [Toycol] Start proxy server on duck protocol, listening on localhost:9292 => Use Ctrl-C to stop [Toycol] Start built-in server, listening on unix:///tmp/toycol.socket
2.クライアントが自作のプロトコルでリクエストメッセージを送ります
(このメッセージは"GET /posts?user_id=1 HTTP/1.1\r\nContent-Length: 0\r\n\r\n"
を意味します)
クライアント側
$ toycol client "quack, quack /posts<3user_id=1" [Toycol] Sent request message: quack, quack /posts<3user_id=1
3.サーバーがメッセージを受け取り、
HTTPフォーマットに変換してアプリケーションサーバーに送り、
そのレスポンスをクライアントに返します
サーバー側
[Toycol] Received message: "quack, quack /posts<3user_id=1" [Toycol] Message has been translated to HTTP request message: "GET /posts?user_id=1 HTTP/1.1\r\nContent-Length: 0\r\n\r\n" [Toycol] Successed to Send HTTP request message to server [Toycol] Received response message from server: HTTP/1.1 200 OK [Toycol] Finished to response to client
4.クライアントはサーバーからのレスポンスを受け取ります
クライアント側
--- [Toycol] Received response message: HTTP/1.1 200 OK Content-Type: text/html Content-Length: 32 quack quack, I am the No.1 duck
(Duckプロトコルの実装はこちら→toycol/examples/duck at main · shioimm/toycol · GitHub)
ユーザーは自作プロトコルを定義することで、自作プロトコルに則ったリクエストメッセージを用いてWebアプリケーションを実行できる(ように見える)のです。
こうした「おもちゃのようなプロトコルを定義できるフレームワーク」ということで、このフレームワークにはToycol(Toy + Protocol)という名前をつけました。
Toycolの実装はこちらです。 github.com
Toycolはシンプルなフレームワークですが、二つの技術的要素を持っています。
ひとつはソケットに対してメッセージの読み書きを伴うネットワークプログラミングの要素。もう一つは、ユーザーが記述するRubyスクリプトを読み込み、解釈して後で実行するメタプログラミングの要素です。
Toycol自体の仕組みはシンプルでトリッキーな要素はありませんが、自分自身にとってはToycolの実装を通じて初めて取り組むことが沢山ありました。
発表準備 & 録画登壇
そうこうしているうちに、提出したプロポーザルの当落案内の時期がやってきました。
わたしはというとその頃にはプロポーザルを提出できて、動くソフトウェアを作っているというだけでとりあえず満足しており、これで落ちたとしても後悔は無いし、その場合はどこかの地域Ruby会議でToycolについてお話しする機会があれば良いなあ、などと思っていたのですが、
> Your proposal for RubyKaigi Takeout 2021 has been accepted
— しおい (Misaki Shioi) (@coe401_) 2021年7月14日
!!!!!!??
(※早寝して起きたらすごいメールが届いていた)
何とacceptされてしまいました(7/15)
嬉しさと信じられない気持ちに圧倒されつつ、ここから必死でToycolの実装を進めたおかげで何とかToycolのメジャーバージョンリリースにこぎつけることができました(7/27)
あとは本編に向けて登壇準備を進めるのみ。
今年のRubyKaigiは登壇者自身が登壇形式を「録画」と「ライブ」のどちらか選べるようになっており、わたしの場合はRubyKaigiの大舞台で平常心を保てる自信が無かったために録画登壇を選ぶことにしました。
日本語スピーカーで録画の場合の締め切りは8/23です。
今度は必死に発表資料を作る日々が始まりました。
その間にプログラマになって丸3年を迎えたり、誕生日を迎えたり、ワクチン接種(2回目)をしたりしつつ、気づいたら発表資料の枚数が140枚を超えていました。
【進捗】発表資料をあれこれ修正した結果スライド枚数が140枚まで増えたのだけど、試しに最初の50枚くらいを読み上げながら時間を測ってみたら6分弱くらいだったので(???)、これなら何とか持ち時間25分内に収まるかもしれないという勇気が湧いてきた(????)
— しおい (Misaki Shioi) (@coe401_) 2021年8月9日
最終的に152枚まで増えた発表資料はこちらです。 speakerdeck.com
資料も大体整ったところで、8/19には半日がかりで登壇動画を録画し、資料と合わせて提出することができました。
なお事前にRubyKaigi運営チームから案内されていた録画ガイドが非常に丁寧でわかりやすく、初めての登壇動画でもスムーズに録画することができました。
RubyKaigi Takeout 2021本編参加
あとは本編を楽しむのみ。
ということで、当日3日間は一参加者としてしっかりRubyKaigiを堪能しました。
(以下はしばらく会期中のツイートが続きます)
今朝は8:00から気合を入れて仕事して、ここまでに一応進捗を出すことができたので準備万端🍔💨 #rubyKaigi
— しおい (Misaki Shioi) (@coe401_) 2021年9月9日
は〜 #rubykaigi めちゃめちゃ楽しいけど、オーガナイザーチームの皆さん本当にお疲れ様です…
— しおい (Misaki Shioi) (@coe401_) 2021年9月9日
お昼ごはん(🍔)を買ってこよう。
13:30再開とのことなので、わたしの発表は14:00~(JST)かな? ※もう気絶しそう
いただきます!! pic.twitter.com/UzeTQG4a7C
— しおい (Misaki Shioi) (@coe401_) 2021年9月9日
RubyKaigi Takeout 2021でお話しした「Toycol: Define your own application protocol」の発表資料はこちらです。
— しおい (Misaki Shioi) (@coe401_) 2021年9月9日
This is a slide from my presentation at RubyKaigi Takeout 2021.
Thank you for your attention!https://t.co/iQGSFDIB87 #rubykaigi #rubykaigiB
(わたしの登壇動画はこちらです。) www.youtube.com
#rubykaigi Day 1お疲れ様でした。
— しおい (Misaki Shioi) (@coe401_) 2021年9月9日
無事に(本当???)デビュー戦を終え、錚々たるRubyistたちに名を連ねることができて&沢山の方に発表を聴いて頂けて凄く嬉しいです。
とはいえやっぱり発表内容的には悔しさが残るので、もっともっと格好良い楽しいコードを書けるようにがんばっていくぞ…!!!!!🍔💨
今日の職場Slack
— しおい (Misaki Shioi) (@coe401_) 2021年9月9日
同僚「しおいさんの登壇をみんなで見るチャンネルはあるんですか?」
上司「こういうチャンネルがありますね👉#times_shioi 」
わたし「それわたしの分報チャンネルですね」
三鷹(論理)の辺りで懇親してました。
— しおい (Misaki Shioi) (@coe401_) 2021年9月9日
RubyKaigiの夜は楽しい…🍻
🍔Tシャツを着ました(Day2) #rubykaigi
— しおい (Misaki Shioi) (@coe401_) 2021年9月10日
これはライスバーガー 海鮮かき揚げ🍔 pic.twitter.com/682yWrv02B
— しおい (Misaki Shioi) (@coe401_) 2021年9月10日
#rubykaigi Day 2も楽しかった〜。
— しおい (Misaki Shioi) (@coe401_) 2021年9月10日
最高のトークを次から次へと浴びた後のRuby Committers vs the Worldで気持ちが高まりました💪🦾
あと皆が心置きなく伸び伸びコードを自慢しているのを聴いていて、この世の中にRubyKaigiがあって良かったなって嬉しくなりました。
#エモリハウス (論理)で懇親してました。
— しおい (Misaki Shioi) (@coe401_) 2021年9月10日
RubyKaigiで沸き立ったRubyistたちが日本全国から集ってわいわいしているの本当良すぎる🍶
※一旦締まりましたがまだやってます
Day 3も楽しむぞ〜🍔💨 #rubykaigi
— しおい (Misaki Shioi) (@coe401_) 2021年9月11日
(干してます) pic.twitter.com/Vv00Jx4x9M
— しおい (Misaki Shioi) (@coe401_) 2021年9月11日
#rubykaigi Takeout 2021、最高だった。
— しおい (Misaki Shioi) (@coe401_) 2021年9月11日
運営チームの皆さん、本当にありがとうございました。
また来年!!!!👋
#rubykaigi 感想戦にのんびり耳を傾けていたら名前を呼んで頂いてあわあわしてしまった。
— しおい (Misaki Shioi) (@coe401_) 2021年9月11日
ありがとうございました🙏
3日目の夜が終わってしまった…(寂しい)
— しおい (Misaki Shioi) (@coe401_) 2021年9月11日
冒頭から心が沸き立つような数々の発表を聴き、チャットとTwitterで人々の熱狂を感じ、🍔に舌鼓を打ち、運営チームの人々に感謝し、懇親会でくだを巻き、あっという間の3日間でした。
緊張しているうちに自分の発表は終わってしまったのですが、チャットやTwitterで沢山の反応を頂いて本当に嬉しかったです。
また、どの発表もとても難し楽しかったのですが、個人的に特に心に残っているのは
- mameさんのTypeProf for IDE: Enrich Dev-Experience without Annotations
- hasumikinさんのPRK Firmware: Keyboard is Essentially Ruby
- tagomorisさんのRactor's speed is not light-speed
- Ruby Committers vs the World
- unasukeさんのRuby, Ractor, QUIC
- MatzさんのKeynote
です。
特にうなすけさんのRuby, Ractor, QUIC
は、自分にとっての「こういうのをやってみたかった…!!(けど色々不足していてできなかった)」を体現したかのようなお話で、しびれました。
そうしてRubyKaigiの3日間が終わった後には、RubyKaigiがあって良かったなあ、と強く強く感じました。
Fukuoka.rb #226 RubyKaigi感想戦参加
かくしてお祭りは終わったかと思いきや、まだ終わっていませんでした。
わたしをRubyKaigiに送り出してくれたFukuoka.rbにて、9/15 RubyKaigi感想戦が開催されました。
わたし自身は途中参加につき、非常に悲しいことに他の人々のトークをあまり聴くことができなかったのですが、Fukuoka.rbのアットホームな空気の中で錚々たるRubyKaigi登壇者メンバーが集い、大変盛り上がっていたようで嬉しいです。
わたしは最後の登壇枠で、主にToycolの技術的な振り返りを発表をした他、最後の締めに 「エクストリームプログラミング」 第二版 の出版記念イベント「 角 征典×角谷 信太郎 XPは何を伝えたかったんだと思う?」から引用しつつ、自分なりに理解した「RubyKaigiとはどんな場所か」についてお話ししました。
(自分の発表者ノートより)
「エクストリームプログラミング」の原著者であるケント・ベックが純粋にプログラミングの可能性そのものを探究する人であるのと同様に、RubyKaigiに集う人々もまた(少なくともRubyKaigiの3日間ばかりは)純粋にRubyの可能性そのものを探究する人々なのではないか。
そして純粋に何かの可能性を探求するというのはやっぱり最高に楽しいし、要するにRubyKaigiは最高である。
#fukuokarb RubyKaigi感想戦お疲れ様でした🍜
— しおい (Misaki Shioi) (@coe401_) 2021年9月15日
終盤近くに参加したので他の登壇者の人々のお話があまり聞けず悲しい…とはいえいつものFukuoka.rbのリラックスした空気で楽しい時間を過ごしました。
あと自分の発表の最後に、一番言いたかった「RubyKaigiは最高」というお話ができたので満足です!!!!
終わりに
RubyKaigi Takeout 2021に登壇できて良かったです。
自分のこれまでの人生の中で一番の大舞台であり、Rubyプログラマとして一つの夢が叶った時間でした。
また、プロポーザルを出すために必死になった結果、松田さんとうづらさんから頂いたアドバイスのごとく「ステージが変わ」ったかどうかはわからないのですが、少なくとも開き直りの精神を身につけることはできたように思います。
今の自分の実力ではまだまだ到底手の届かないような格好良いソフトウェアを作れる日が来るのを待つのではなく、今持っているものの中で最高のソフトウェアを作るのだ、という気概を持つことができました。
一方で、もっと自分に経験と知識があれば、もっともっと格好良い楽しいソフトウェアを書けたかもしれないのに、という心残りもあります。
こうした心残りと、まだ知らないRubyとコンピュータの世界へのわくわくを来年以降への糧としていきたいです。
最後に、プロポーザルの提出に背中を押してくれたAsakusa.rbの人々とFukuoka.rbの人々(特にいつも力強く鼓舞して下さるうづらさんとjimlockさん)、
プロポーザルの英文添削に加えて技術的なアドバイスを下さったokuramasafumiさん、
いつも見守り、応援してくれる上司(そして職場の人々)、
最高のRubyKaigiを作ってくれたRubyKaigi運営チームの人々と他の登壇者の人々に感謝しています。
あと実装中や発表準備中、そしてRubyKaigi本編が終わってからも、自信がなくなりそうになった時Fukuoka.rbのebiflyyyyyyyyさんからかけてもらった言葉には何度も励まされました。
明日のしおいさんは今日のしおいさんよりも強いですし、明後日のしおいさんはもっと強いですよ
— 性格がおだやか (@ebiflyyyyyyyy) 2021年6月27日
2022年もプロポーザルを出せるように頑張るぞ!
おまけ
#kaigieffect ①
わたしの(現時点での) #kaigieffect はこれです(???) pic.twitter.com/8kdVv89Ayg
— しおい (Misaki Shioi) (@coe401_) 2021年9月12日
#kaigieffect ②
次はわたしの2つ目の #kaigieffect であるところの「dRubyによる分散・Webアプリケーション」をこつこつ読む。 pic.twitter.com/ZsFk0NPH6e
— しおい (Misaki Shioi) (@coe401_) 2021年9月16日
二冊とも絶賛読書中です。楽しい!!