Google Summer of Code に参加した話
この記事は CAMPHOR- Advent Calendar 2022 の 24 日目の記事です。
クリスマスですね。みなさんはいかがお過ごしでしょうか。僕は金曜ロードショーでホームアローンを見たりコストコへショッピングに行ったりします。
ところで、Google Summer of Code 2022 に Chromium プロジェクトに参加してきたので、参加しようと思ってからプロジェクトを終えたあとまでの話を一通りしようかなと思います。
GSoC とは
Google Summer of Code - Wikipedia より
Google Summer of Code (Googleサマーオブコード 略称GSoC) は2005年の5月から8月に初めて開催され、その後毎年行われている恒例のイベントで[1]、Googleがフリーソフトウェアやオープンソースのプロジェクトを指定し、その夏の間に課題をクリアした数百人の学生に賞金を支払う制度である。
要するに数ヶ月ほど OSS にコントリビュートして Google からお金をもらうというプログラムです。実は Wikipedia の情報が遅くて、現在では対象者は学生に限定されておらず、期間も秋の終わり頃まで延長することができます。
2022 年の GSoC のスケジュールが公開されています: https://summerofcode.withgoogle.com/programs/2022
参加するまで
GSoC の存在を知ったのはさんぽしさんのブログを見たのがきっかけでした。OSS 自体にそこまで興味があったわけではないんですが、大規模な OS の開発をやってみたいというのはぼんやりと思っていたので、GSoC を機にやってみようと思いました。
3 月ごろに GSoC でコントリビューターを募集する OSS プロジェクトの一覧が発表されたので、その中で OS の開発ができそうなものをいくつかあさりました。HaikuOS や FreeBSD なども候補に上がったのですが、最終的に応募したのは Chromium のみでした。頑張れば複数の OSS に応募することもできたのですが、ちょっとしんどかった。
Chromium
Chromium プロジェクトは Chromium のみを管理しているわけではなく、ChromiumOS という Chrome に対する Chromium の ChromeOS 版みたいなものも持っています。というわけで ChromeOS 絡みの開発もやってます。
2022 年に Chromium が出していた Idea List こちらです: https://docs.google.com/document/d/1QnqhnsmEnHxoD1j7sWNFL5nybQ7rh5bMgPuf3NQLAtg/edit この中の 7 つ目、VirtIO Balloon Performance Improvements というテーマに興味を持って応募を決めました。
どんなテーマかというと、Linux kernel の VirtIO Balloon のドライバの CPU 使用率が高いからそれのベンチマークをとってパフォーマンス改善してみようという内容です。
VirtIO Balloon とは何かというと、VM とホストマシンの間でメモリを共有する仕組みです。VirtIO のデバイスの一つとして実装されています。
具体的なゴールが定まっていないためなかなかハードなテーマでした。
プロポーザル
これに応募しようということで、プロポーザルを書こうと思いました。まずはこのテーマに応募する前にやっておいてほしいことリストが公開されていたためそれをやりました: https://docs.google.com/document/d/1l8Tp-HJAJInqv2Yld_L2PazQX-bh6Z41ikDdBvSe270/edit
といったことをやりました。やってほしいことリストには他にも「実際に改善を加えてみよう!」とかもあったんですが、さすがに厳しくて諦めました。
そしてそれに加えて Linux と crosvm のコードを読んだり記事を調べたりして VirtIO Balloon の仕組みを理解し、プロポーザルを書きました。
これまでやってきた中で理解した内容をすべてアウトプットするように努めました。また、さんぽしさんのブログを参考にして、スケジュールをできるだけ具体的に書くなどしました。
出来上がったのがこちら: https://docs.google.com/document/d/1yKPODnqaGJlPQkSUjDDdS9ZiDlMDhsm2lrxBAxy0JBA/
書いた内容はこんな感じ
- VirtIO Balloon の概要や、抱えている課題について
- VirtIO Balloon の詳細な処理内容 (ソースコードのレベル)
- パフォーマンス計測・評価の方法
- ざっくりしたスケジュール
プロポーザルを書くまでの過程で、メンターにたくさんメールで質問をしました。
- 「この手順でビルドしてみたけどできなかった」
- 「CPU の使用時間ってどうやって測ったらいい?」
- 「VirtIO Balloon ってどうやって動かしたらいい?」
など、やってみてわからない・できないことがあったらメンターに連絡していました。(Chromium ではプロジェクトが始まる前に各テーマごとにすでにメンターが決まっているのです。)
また、プロポーザルの初稿が書けたらそれもメンターに見てもらってフィードバックをもらいました。2 往復ほどしてメンターから「ええんちゃう?」というフィードバックをもらえたので提出しました。
このように、プロポーザルを出す段階から OSS のメンテナとたくさん連絡を取るのがかなり大事だと思いました。「迷惑かな...」とか思っちゃうんですが、恥を忍んでなんでも聞いてみるのがいいと思います。
プロジェクト開始
5 月の終わり頃にメールで合格通知が来ました。
GSoCのproposalがacceptされたぞー!!!!
— Saza (@Saza_xxx) 2022年5月21日
ChromiumプロジェクトでLinux kernelとcrosvmというVMMをいじります pic.twitter.com/XIuGPw1hXC
固定ツイートにするぐらい嬉しかった。
プロジェクトが始まるまで半月ほどあったんですが特に何もしてなかったと思います。一回メンターと面談してプロジェクトの進め方の話をしたぐらいでしょうか。
プロジェクトの進め方としては以下のような感じでした。
- 週に 1 回メンターと 1on1
- 進捗確認
- 今後の方針決め
- 週に 1 回 ChromeOS Virtualization チームとのカジュアルチャットがある
- 進捗報告や技術的な相談
- あまりカジュアルという感じではなかったがたまに普通の雑談もしていた
- メンターが日本に来ているので時差なし (とてもありがたい)
僕は英語喋ったことなかったので英語でのミーティングがとても大変だったんですが、Google Meet の字幕機能を使って乗り切りました。メンターも英語が苦手な僕に合わせてゆっくり話したり僕のペースに合わせたりしてくれました。とても親切な方でした。
6 月
まずはコントリビュートする手順に慣れる練習を兼ねて、crosvm の VirtIO Balloon についてのドキュメントを追加しました: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3697995
その後、ベンチマークを作成してボトルネックの特定をしました。VM とホスト間でメモリを受け渡しする部分が遅いというのがわかりました。
7 月
このメモリを受け渡しする部分のアルゴリズムに改善を入れました。
メモリの受け渡しとは具体的に何かというと、ゲストからホストに解放・または確保したページの PFN (Page Frame Number) を伝えるということをします。
そこで、現状では PFN のリストを伝えるということをします。例えば、ゲストが PFN 3, 4, 5, 8, 9, 13 のページを確保してそれをホストに渡すときには [3, 4, 5, 8, 9, 13] といった整数列を渡します。
これを、連続したページをまとめて (offset, length) のペアで渡すようにします。上の例でいうと、[(3, 3), (8, 2), (13, 1)] といった配列を渡すことになります。
この改善を入れると非常に高い効果が出ました。
ところがこの改善は VirtIO Balloon の仕様に反しています。
The driver constructs an array of addresses of unused memory pages. These addresses are divided by 409614 and the descriptor describing the resulting 32-bit array is added to the inflateq.
なのでこの改善を入れると他の環境で動かなくなるため、upstream に受け入れられません。これは調査として行ったという側面が強いです。(非常に高い効果が出たためこれについては ChromeOS チームでさらなる研究がされるとかされないとか話してました。)
8 月
今度は実際に upstream に受け入れられる改善として、メモリ割当アルゴリズムの改善を行いました。
現状ではドライバは Balloon に 1 ページずつ割り当てるようになっているのですが、これを複数ページを割り当てる必要があるときは一気にメモリを割り当てるようにするという感じです。具体的な実装で言うと、alloc_page()
を使っていたのを alloc_pages()
を使って割り当てるということをしました。
これを実装するにあたり死ぬほどバグを生んでしまい、3,4 週間ほどデバッグに溶かすということをやっていました。その間進捗は出ていなかったため大変メンタルに悪い時間でした。
なんとか実装した結果がこんな感じでした。
ボトルネックに効いていないためさっきより効果は地味ですが、たしかに改善しているというのがわかりました。
9, 10 月
他社インターンに行っていたためおやすみしていました。
11 月
crosvm 以外の環境で動かないという厄介なバグを発見し戦っていました。メンターがめっちゃ手伝ってくれたのでなんとかなりました。ありがとうございました...
12 月
GSoC としては 11 月末頃に終わったんですが、さらに延長線としてこの改善を upstream に送るというのをやりました。ChromeOS チームに Linux kernel のメンテナがいるため、その方からレビューいただくなどして upstream に送る準備をしました。
そして満を持して昨日 upstream に投下しました: https://t.co/ZICnAqa9Mc
果たして merge されるのか... ドキドキです。
終わり
こんな感じでだらだらのんびりとやっていたような気がします。なんたってまだ延長線の途中ですからね...
パフォーマンス改善というゴールが明確でないプロジェクトに取り組むのはなかなかメンタル的にしんどかったです。ですが憧れの Linux kernel コントリビューションのきっかけになったり、ChromeOS チームの方々とたくさんお話できたりと、本当に貴重な経験をさせていただけて楽しかったです。勇気をもって GSoC に応募して良かったと思います。
メンターの方や ChromeOS チームの方々には本当に感謝してもしきれません。特にメンターの方には本当にお世話になったんですが、最後のミーティングで英語力が不足しすぎて Thank you しか言えなくてすみませんでした。親切な素晴らしいメンターでした。
また、これを機に OSS に興味を持ちました。Linux kernel へのコントリビュートを続けていくのもできたらいいなと思いますし、Kubernetes など他の OSS にもコントリビュートしてみようと思っています。OSS を身近に感じる良い機会になりました。
GSoC やってみたい方へ
ぜひやってみましょう。GSoC の応募にありがちな障壁をまとめてみました。
プロポーザルの書き方がわからない
応募したい OSS プロジェクト側から、期待されるプロポーザルの内容などが公開されていると思うのでよく読みましょう。過去のブログなどを見て参考にしましょう。よくわからんかったらその OSS のコミュニティに連絡して聞いてみましょう。積極的にメールを飛ばす姿勢はコントリビューターとして評価されると思います。
英語が心配
なんとかなります。僕も英語喋ったことなかったけど Google Meet のおかげでなんとかなりました。多分相手も完璧な英語を喋ってくれることを期待してないと思うので気楽にいきましょう。
大学の講義やテストなどとかぶって厳しい
今の GSoC は期間についてかなり柔軟に対応してくれるようになっているのでなんとかなると思います。それでも厳しいって?留年はいいぞ