kateinoigakukunのブログ

思考垂れ流しObserver

Swift 6.2でWebAssemblyサポートを公式化した

Swift 6.2 のリリースで、公式に WebAssembly ターゲットをサポートしました。

https://www.swift.org/blog/swift-6.2-released/#webassembly-support

6.1から何が変わったか

SwiftWasm 6.1のリリースを自慢したい でも書いた通り、6.1 の時点で必要なパッチはすべてアップストリーム済みでした。ただし当時は WebAssembly 向けの Swift SDK を swiftwasm 側が配布していました。6.2 からはこれが swift.org から提供されます。基本的には「配布元が変わっただけ」で機能差はありません。

とはいえこれは信用の話として効いてきます。これまでは Swift SDKサードパーティからの配布だったため、いくつかのSwiftパッケージにWasm の CI チェックを入れる提案に渋い反応をもらうことがありました。今回公式化されたことで話が通りやすくなり、実際にいろんなパッケージで Wasm ビルドを CI に入れてもらえるようになりました。

WasmKit が同梱

6.2 の OSS ツールチェイン(Xcode 同梱版ではなく swift.org で配布される方)には、僕がswiftwasm で引き継いで開発している WebAssembly ランタイム WasmKit も同梱されています。コンパイラツールチェインにWasmランタイムが同梱されているのはなかなか珍しいと思います。

おわりに

公式ドキュメントに step-by-step のガイドがあるので試してみてください。 https://www.swift.org/documentation/articles/wasm-getting-started.html

2024年の振り返り

大学院

今年はM2をやっていた。授業はM1で取り切っていたので研究をひたすら頑張る形。 去年は渡米や諸々によりほとんど進捗がなかったが(たいへん申し訳ない気持ち)、今年は国際ジャーナルを通せたので良かった。

なお修論は全く別のテーマで書いているので現在進行形で大変マズい状況。修了したい。

仕事

引き続きGoodnotesでパートタイムで働いている。ロールも変わらずSwiftコンパイラツールチェインとWebAssemblyを仲良くさせる仕事。

ちょうど今年web.devで事例紹介の記事が公開されたので貼っておく。 Goodnotes everywhere  |  web.dev

チームメイトのおかげでプロダクトも育ってきており良い感じ。今年も相当量のSwiftのコードが新しくWebと共有できた。クロスプラットフォームなコードが増えていくたびちょっと嬉しい。

就職

就活をしてもいいかなと思ってはいたが気がついたら25卒のウィンドウが閉じていたので結果的にほとんど何もしていない。

ありがたいことに大変良いオファーをもらえたので4月からもGoodnotesで働き続ける。ハーフタイマーだったのがフルタイマーにジョブチェンジ。拠点も移すことなく東京からフルリモート。

OSS

Swift

今年は仕事で必要な話しか進められなかった印象。目立った(といっても別にどこかで宣伝したわけじゃない)話としては

地味な話題としてはswift-foundationへの移行に伴い大量のパッチを書いた

コミュニティでは自分以外からWasmに関する話がいくつか出たのはよかった。

Ruby

ruby.wasmにDynamic Linking対応を入れた。本質的に難しくないはずなんだけど、ビルドプロセスが複雑になりすぎててなかなか手間取った。

その成果としてRailsがブラウザで動くようになった。なんとMastodonRedmineも動いた。 Mastodonがブラウザで動いて何が嬉しいのかは自分でも分かってない。無意味で楽しい。

登壇

招待して頂いたEuRuKoではElixirのJosé Valimと話せて良かった。 サラエボ旅行のハイライト(たまたま行きも帰りもMatzと同じ便だった):

旅行

しれっと友達と南米旅行に行ってきた。かなり良かった。英語が通じないことと高山病とトイレットペーパーが流せないことだけは大変だった。

まとめ

比較的健康に過ごせたので良かったと思う。では修論に戻ります。

RubyKaigiとiOSDCでWasmの話をしてきた

09/08-10に三重で開催されたRubyKaigi、09/10-12に東京で開催されたiOSDCにどちらもスピーカーとして参加してきました。

カンファレンスはしごされた方はお疲れ様でした。

RubyKaigi Keynote

初めてのRubyKaigiでの発表で、さらにキーノートで、さらにトップバッターという大変貴重な体験でした。いやー緊張した。1

当日のスライドはこちら。

Ruby 3.2でサポート予定のRubyのWebAssembly/WASI対応について話してきました。

前半でモチベーションや出来るようになったことをデモを交えつつオーディエンスと共有して、後半は実装について自分の好きなことを話す、という構成でした。

syntax_treeを使ったデモはちょっと上手くいかなかったんですが 2、 一番見せたかったIRBSVGを表示するデモがうまくいって良かったです。IRBのデモはこちらで遊べます。

irb-wasm.vercel.app

少しでもKaigiを盛り上げられたなら嬉しいです。発表練習に付き合ってくださった皆さんありがとうございました。

さっそく遊んでくださっている方もちらほら見られたり、「WebAssemblyのことは今まであまり知らなかったけど興味が出てきた」といった声を頂くこともあり、大きな場で話す機会の重要性を実感しました。

最終日途中でiOSDCの方に移動してしまったのでクロージングはきちんと見られていないんですが、TRICKの受賞作品をブラウザで動かすというアツい展開もあったようですね。

気になったトーク

Towards Ruby 4 JIT - RubyKaigi 2022

コンパイラ側の気持ちに興味があるため、JITの話はかなり面白かったです。自分で手軽にJITコンパイラをかける口があるとのことなので試してみたいと思います。特にLLVMよりコンパイル時間が安く済むと噂のCraneliftは一度試してみたいので。

Implementing Object Shapes in CRuby - RubyKaigi 2022

Object Shapeの話も直感的にはグッと速くなるのかなと思っていたんですが、意外と伸び悩んでいたのでどこに原因があるのか、そもそもここにネックはないのか?と色々と考えることがあって面白いなと。これも追っていきたいです。

Stories from developing YJIT - RubyKaigi 2022

例によってこれも実際には聴けていないんですが、反応を見る限りかなり自分の興味に合いそうなので気になっています。動画が出たらすぐに見たい。

おいしいRubyKaigi

ありがたいことに大変おいしい思いをさせていただきました。 うなぎも松坂牛もウマー😋 ご馳走様でした。

iOSDC

RubyKaigi最終日の昼過ぎに会場を出て、iOSDC初日の終わりの方から参加していました。iOSDCでは今年で通算4回目の発表でした。

懲りずに自分がメンテしているSwiftWasmプロジェクトについての発表だったんですが、今年はプロダクションでの採用事例やデモを多めにすることで、「あれ、意外ともう使えるんじゃないか?」と思ってもらうことがメインの狙いでした。どうでしたか?

また、実際に手を動かしてコントリビューションしてくださる例もあり、大変ありがたかったです。

気になったトーク

Xcode が遅い! とにかく遅い!! 遅い Xcode をなんとかする方法 by Yoshimasa Niwa | トーク | iOSDC Japan 2022 - fortee.jp

ある程度大きなプロジェクトを経験したことがあったので、共感できることも多かったです。正しく根本の原因を特定し、現実的なワークアラウンドに落とし込んでいく様子はソフトウェアエンジニアリング感がありこうありたいなと思いました。

まとめ

RubyKaigiではほぼ皆さんはじめましての状態だったんですが、おかげさまで楽しいコミュニケーションができました。これからもよろしくお願いします。 iOSDCでは久しぶり皆さんにもご挨拶できたのでオフライン開催ありがたかった…

来年もどちらも参加したいです。(幸い来年は日程が離れてそう)


  1. 緊張の結果がこれです https://twitter.com/kateinoigakukun/status/1567708097900331008

  2. これはいまだに原因が分からない… ライブコーディングはむずかしい。

GoodNotesでSwiftWasmの仕事を始めた

近況アップデート

5月の初旬からGoodNotes社で働いている。 GoodNotes社はiPad向けノートアプリGoodNotesを開発しているところ。

実は、去年の10月くらいからGoodNotesの人々がSwiftWasmプロジェクトにコントリビュートしてくれていた。 詳細は控えるが、GoodNotesアプリのコードベースをWebAssemblyにコンパイルして、クロスプラットフォームに移植することが目的。

コミュニティのDiscordでそこそこの頻度で社員と議論していたことで、お互いに顔見知りになり、声がかかったという流れ。

働くモチベーションとしては、

  • 自分が育てた技術を使ったプロダクトで価値を届けたい
  • (恐らく)現状自分の価値が最も高い環境でどの程度の評価をされるのか知りたい

の2つが大きい。

ロールとしては、プロダクト開発で発生した問題の相談に乗ったり、得られたフィードバックを元に実際に手を動かしてSwiftWasmツールチェインを改善したり、とコンサルタント的な感じ。 大規模なアプリ故のパフォーマンス問題や、製品レベルの品質を達成するための課題など、見えてこなかったポイントが見えてきたので楽しくやっていけそう。

オフィスはロンドンと香港にあるが、割とフルリモートで働いている人が多く、自分も日本からリモートで働いてる。 タイムゾーンを跨いでいるのでコミュニケーションは基本非同期だが、情報共有の工夫やドキュメンテーションの文化のおかげでなんとか働けている。

英語は周りに介護してもらってなんとか…という感じ。

まだ始まったばかりだが、ひとまずここ2週間くらいはチームメンバーからの信頼を得るためにあくせく働いている。

muslでビルドするにはmusl.ccが便利

Binaryenのビルド済みwasm-optを使うとセグフォする現象に遭遇した時、ビルドを手元で再現するためにmuslを使う必要があったのでメモ。1

musl libc

muslはlibcなので、コンパイラgccのままsysrootを差し替えることで大体うまいことコンパイルできる。

この設定をmusl-toolsパッケージのmusl-gccラッパーコマンドが勝手にやってくれるが、C++用のラッパーが用意されてなかったりスッとはビルドできない。あとツールチェインに入ってるSanitizer達がglibcを想定してビルドされてたり出来ないことが結構ある。

なので、最初からmuslをターゲットとしてビルドされたツールチェインが欲しくなり、そこでビルド済みのmuslツールチェインを配布しているmusl.ccが便利。2

$ curl -LO https://musl.cc/x86_64-linux-musl-native.tgz
$ tar xfz x86_64-linux-musl-native.tgz
$ tree -L 1 ./x86_64-linux-musl-native
./x86_64-linux-musl-native
|-- bin
|-- include
|-- lib
|-- libexec
|-- share
|-- usr -> .
`-- x86_64-linux-musl

CMakeで使う

musl.ccのツールチェインはsysrootをgccコマンドの相対で設定してくれるので、CMAKE_C_COMPILERさえ設定していれば、特に追加で指定する必要はない。

cmake ../.. -G Ninja \
  -DCMAKE_C_COMPILER=./x86_64-linux-musl-native/bin/gcc \
  -DCMAKE_CXX_COMPILER=./x86_64-linux-musl-native/bin/g++

  1. これは結局muslのスレッドスタックサイズのデフォルト値がglibcよりかなり小さくてスタックオーバーフローしてただけだった https://github.com/WebAssembly/binaryen/issues/4401

  2. これはOfficialではないがOpenJDKとかでも使われてる

Rubyのコミッタになりました

実は先日 ko1さんとmameさんから推薦をいただき、Rubyのコミッタになりました。

ここ数ヶ月間、Rubyアソシエーションの開発助成プロジェクトとしてCRubyのWASIサポートを進めており、WASIのプラットフォームメンテナが必要ということで。

WASI対応の話はPublickeyさんに良い感じにまとめていただきました。詳しい実装の話は後日書こうと思います。1

www.publickey1.jp

正直Rubyのことを聞かれても答えられる自信はありませんが、CRubyの実装はほんのり分かるようになりました。あとビルドスクリプトはどこもつらい。2

という訳で、晴れてSwiftとRubyのコミッタという謎の人材になりました。 引き続きどちらもやっていくので、よろしくおねがいします。


  1. 書きました An Update on WebAssembly/WASI Support in Ruby | by kateinoigakukun | ITNEXT

  2. SwiftはカスタムターゲットまみれのCMake、CRubyは4000行以上のconfigure.acが…

TypeProf for IDEの開発をお手伝いしました at クックパッド

TL;DR

インターンの内容

TypeProfはクックパッドでフルタイムRubyコミッタをされている@mametterさんが開発しているRubyの型プロファイラです。 Rubyのプログラムにできるだけ型注釈を入れずに抽象解釈によって型を推論する、という面白い特徴があります。

Ruby 3.0ではRBSのプロトタイプを生成するためのツールとしてRubyにバンドルされています。

github.com

今回のインターンでは、TypeProfの解析結果を利用したRubyのLanguage Serverの実装をお手伝いしました。

TypeProf for IDEについては今年のRubyKaigi Takeout 2021のKeynoteで発表があったので、雰囲気を知りたい方はこちらを見てください。

www.youtube.com

www.slideshare.net

実装

そもそもRubyを触るのが久々かつ、TypeProfがそこそこ大きいプログラムであったため、binding.irbデバッグ可能な環境を作るところからはじめました。

これを初手で準備したことでその後のコードリーディング効率が格段に上がりました。やはりデバッガは偉大。

Add --port option to lsp server for debugging purpose by kateinoigakukun · Pull Request #34 · ruby/typeprof · GitHub

その後mameさんに助けてもらいながら数種類のコードジャンプを実装しました。 ジャンプ先候補はTypeProfの解析結果を使っているので、解析器自体の実装も勉強できて良かったです。

もうひとつ面白い改善として、コード補完の高速化を行いました。

TypeProf for IDEではユーザが1タイプするごと (textDocument/didChange) にプログラムを解析し直すのですが、解析の仕組み的に一回の解析にかなり時間がかかります。 オリジナルの実装では解析中サーバスレッドをブロックしていたため、タイプするごとに解析待ちのリクエストが溜まっていました。

さらに、コード補完 (textDocument/completion)では変更後のプログラムを検証する解析とは別の解析がサーバスレッドで行われているため、1タイプごとに貯まる重いタスクが更に増え、若干もっさりしていました。

LSPではdidChangeは通知であり、すぐに結果を返却しなくても良く、更にコード補完リクエストもリクエストとレスポンスの順序を気にしないメソッドなので、高速化のために解析スレッドを分けることにしました。 また、新しい didChange 通知が来た時点で前の状態での解析結果は無効になるため、解析を途中で打ち切る機構を追加しました。

f:id:kateinoigaku:20210912110945p:plain

before after
typeprof-before typeprof-after

github.com

その他にも色々と実装できて楽しかったです。

インターン中のPRs

Ruby本体への貢献

TypeProf for IDEは最新の開発版MRI (Matz's Ruby Interpreter) のAPIを使っており、CIではデイリービルドされた最新のRubyバイナリを使っています。

具体的には、ruby/setup-rubyGitHub Actionsのアクション経由で ruby/ruby-dev-builder でビルドされた成果物を使っていました。

しかし、ある日直近で入ったAPI変更に追従する変更をTypeProfに入れたところ、CI上のテストが失敗し始めました。

調査したところ、ruby/ruby-dev-builderのデイリービルドがmacOS上で数十日間失敗しており、最新のバイナリが全くアップロードされていないことがわかりました。具体的には、macOSにデフォルトで同梱されているGNU Makeのバージョンが古いことが原因で、最新のruby/rubyMakefileを正しく解釈できていませんでした。

そして、特定のビルドオプションを付けたときのみ再現する問題であったため、ruby本体のCIを奇跡的に通り抜けていました。

macOSはGPLv3を避けるためにGNU Makeのバージョンを3.81で止めている。ちなみに3.81は2006年リリース。最新は4.2

とりあえずの対処としてGNU Make 3.81で最新のバージョンと同様の動作をさせるためのワークアラウンドを追加しました。

github.com

ということで晴れてRuby Contributorの実績も解除できました。

クックパッドの環境

ruby-devチームの朝会では@_ko1 さんと@mametterさんがRubyの話を、僕がSwiftとWebAssemblyの話をする機会があったり、母国語で言語処理系のプロと働けるとても貴重な環境でした。

感想

Ruby自体の経験は浅かったものの、言語処理系や巨大プロジェクト開発の経験のお陰で、ある程度の貢献ができたかなと思います。

また、Ruby開発には単純に人手が足りず、自分でも貢献できそうなインパクトの大きいタスクが残っていたり、出来ることはたくさんありそうなので、時間を見つけて継続して関わっていけたらなと思います。

今回のインターン中関わってくださった皆さんありがとうございました。