フルタイムOSSコミッタを始めて2か月経った

Shopifyに入社してRubyJITコンパイラを書く仕事を始めてから2か月経った。 前職の退職エントリ では今後やりたいことを書いたりしたが、実際OSS開発を仕事にしてみてどうだったかみたいなことを書いておく。

シリコンバレーでのリモート生活

3年前に妻とアメリカに移住し、今年永住権も取得した。 Shopifyは本社はカナダにあるし2020年5月からフルリモート企業なのだが、 前職の本社があったシリコンバレーのあたりからそのまま引っ越さずに暮らしている。

なぜシリコンバレーに住み続けるのか

フルリモートである以上はカナダ移住のためのビザのサポートを会社がする動機もないため、 現職においても住む国の選択肢は基本的に日本かアメリカになると思っている。

飯が安くて美味いのを主な理由として妻も僕も住むならアメリカより日本の方が好きなのだが、 住む地域ベースで多くの企業が給料に傾斜をかけてくることを理由にシリコンバレーに住み続けている。

東京だと、現地の企業では良くて年収1000万円、金払いのいい外資に行くと2000万円という感じだと思うが、 シリコンバレーに住んでいれば、スタートアップでも $180,000 (2600万円) あたりが割とよくある感じだし、 上場してる大きめの企業だと、結構多くの人が $360,000 (5200万円) くらいのTotal Compのオファーをもらってそうな雰囲気を YouTubeやlevels.fyiから感じる。

リモートペアプログラミング文化

前職では様々な人と定期的に1on1をすることでリモートでのコミュニケーションを活発に行なっていた。 Slackより1on1の方が深い関係を築きやすいので、特に転職したばかりの新人の自分はそれを積極的にやっていく必要があると考えたが、 現職では、マネージャー以外と定期的な1on1をしてる人が少なそうに見えた。

一方、Shopifyは全社的にTupleというペアプロサービスを導入していて、定期的なペアプロミーティングを毎週複数持っているみたいな人は逆に多そうだった。同じ仕事をしてるチームメンバーとはペアプロをし、それ以外の人たちとは突発的な1on1を申し込むという感じで関係性を築いていくことになろうかと思っている。

北米東海岸と日本の時差

前職はアメリカ在住の社員は基本西海岸にいるという感じだったが、 現職ではアメリカでもカナダでも東海岸タイムゾーンに住んでる人がかなり多いことに違いを感じている。

日本と西海岸でミーティングをする場合、双方の働いてる時間が被る1~2時間を使うとまともな時間にそれを行なえるが、 日本と東海外だと時差が13時間あり、両者が業務時間内になるタイミングでミーティングをするのが不可能という感じになっている。

普段は西海岸に住んでるので問題ないのだが、カンファレンスで日本に出張したついでに日本に滞在して一時的にそこから働くということをすると、ミーティングが必要な仕事は全てアメリカに帰るまで先延しみたいな感じになる。僕は業務時間外にミーティングをしたくないし相手にも強要したくないので、現状特に解決方法がない感じになっている。

OSS開発とビジネスインパク

コンパイラエンジニアというキャリア

今回の転職で、分散システムの開発というかなり求人の多い職種から、 言語処理系の最適化というニッチな分野にキャリアチェンジした。 コンパイラを商品として提供している会社ならまだしも、 特にそういうわけでもない会社で、誰でも無料で使える言語処理系の最適化を仕事にするというのは、 会社に予算を充ててもらうハードルが高そうなイメージがある。

言語処理系開発というキャリアについて考えるとき、 GoogleでWebAssemblyを開発していたが病んでしまった人 のことをよく思い出すのだが、 なかなか経営陣に人や予算を割り当ててもらいにくそうな仕事に就いている という点に関しては常に意識しておく必要があると思っている。

基盤開発と利益部門の関係

その一方で、過度に悲観的になる必要もないと最近は考えている。 というのも、どれだけOSSを活用してプロダクト開発に集中しようとしている組織でも、 自分たちの特殊なニーズに合わせて基盤技術の改善を行なうことで開発や運用が効率的にできるようになる状況はいくらでもあるし、 特に大きな組織ではその価値がスケールしやすい。 僕はRubyRailsOSS開発を主に行なうグループに所属していて、大体40人くらいいるのだが、 社員が9000人ほどいる会社ではそこに投資しすぎということにもならないのだろう。

現職の例だと、Rubyを使ってプロダクトの開発と運用を行なっていく上で JITGCの改善によって速度改善が得られればユーザー体験が向上するし、 メモリ使用量が減れば台数が減らせてコスト削減にもなる。 全社的にサーバーサイドにRubyを使っていて、サーバーの数も社員の数も多いため、 この基盤の改善が会社に与えるインパクトは並の企業より大きいことになる。 そうすると、利益部門が出した売上の一部を基盤開発に充てる経営妥当性も十分説明できそうな感じがする。 特にShopifyの場合はCEOが元Railsコミッタなので、そこを誰かが説明してあげる必要もないという強みもある。

仕事の評価と待遇

RubyRails自体のフルタイム開発を仕事にしている他の日本人と話すと、 Shopifyみたいに開発目標を立ててチームでOSS開発をしてインパクトレビューもして給料に反映させますみたいな環境より、 待遇がある程度犠牲になっても何でも自由に開発していいみたいな会社の方が好き、 という意見を聞くことが複数あった。

僕もお金を稼ぐ目的は経済的に自由になって選択肢を増やすことなので、 そもそも仕事も自由にしたいという気持ちには一定の共感があるが、 自分がやりたい仕事を取ってきたり自分の仕事を適切に評価してもらうためにコミュニケーションしたりすることに慣れたので、 そこにはそれほど抵抗を感じないようになった。 むしろ、成果を出したらそれが待遇にも反映されることで得られる満足感もあると思うが、 そこが実際どうかは実際のレビューを経てみないと何とも言えなそう。

カンファレンス登壇業務

僕のグループではカンファレンス登壇が主要な業務の一つという風にマネージャーも認識していて、 RubyKaigiのトークの準備をするので他の仕事が1週間全く進捗しませんみたいな状態でも誰も文句を言わない雰囲気がある。 登壇1回するごとにちょっとボーナスももらえるのでお得。

自分たちが作る基盤をプロプライエタリではなくオープンにやるのは、 それによってより多くの環境でテストされたり、社外からもコントリビューションが来たりすることで品質が上がるなどのメリットがあるからだと思うが、 実際にそれが起こるようにして自分たちの仕事のインパクトを大きくしていく上でカンファレンス登壇は実際に必要な業務だと感じる。

キャリアチェンジの感想

前職では自分の書いたコードが直接売上に貢献しうる仕事をしていたので、 OSS開発なんか仕事にして大丈夫かという不安も以前はあったが、 実際に入社してみると、自分が今最も技術的に興味のある課題に取り組めることがとても楽しく感じる。

シリコンバレーに住んでれば面白くて待遇の良い転職先なんていくらでもあるので、 変に先のことを気にして何かを妥協するより、 今一番面白いと思えることができる環境に今後も身を置き続けようと思うようになった。

Neovimを一瞬でVSCode並みに便利にする

去年8年ぶりに vimrc を書き直した時はLSPの体験があんまりよくなくてLSPなしでNeovimを使い続けていたのだが、様々な言語のOSSをメンテする都合で用途に応じてIntelliJVSCodeとNeovimの三刀流で暮らしていた結果、可能ならNeovimに寄せたいけどそれならLSPを使いたいなということになり、今回LSPの所を真面目に設定し直して、かなり良い体験になっている。

正直Neovimの設定はVSCodeのそれに比べたら面倒なんじゃないかという印象がありサボっていた節があるが、実際にやってみるとVSCodeと同程度に簡単に済む方法もあったので紹介したい。

何故Neovimなのか

LSPの話の前に、タイトルだけ見た人がそもそも単にVSCode使えばいいじゃんと言いそうなので、どうしてIntelliJVSCodeではなくNeovimに揃えようと思ったのかについて書いておく。

IntelliJの不便なところ

JetBrainsのIDEにはRubyとCを両方正式にサポートしているIDEがなく *1 、CRuby開発者的には大変不便である。やるならRubyMineとCLionをいったり来たりしないといけないが、C-なんとかでウィンドウ切り替えをしている都合、エディタに2つもショートカットを使うのは正直勘弁願いたいという状態である。仮にショートカットの問題がなかったとしても、一窓で完結できるVSCodeやNeovimに比べて体験が劣るのは変わらないと思う。

それがモチベーションでVSCodeを使い始めたのだが、KotlinやRubyIntelliJやRubyMineの方がVSCodeより圧倒的に言語サポートが充実している *2 ので、できればIntelliJにCをサポートしてもらうのが一番望ましいのだが、そうなりそうな見込みはない。

次に困るのが、Vimのタブに相当するものがないこと。Vimはタブの中で画面を分割し、分割された窓の中で更に複数バッファを持つという感じなのだが、IntelliJではトップレベルで画面を分割し、その中で複数バッファを持つという感じなので、VimのバッファのようなものはあるがVimのタブはないという感じになっている。Vimのタブは同じファイルの別の場所のコンテキストを保存しながら作業するといった用途に便利で、これがないのは大変辛いのだが、まあこれもIntelliJに入ることはないだろう。

Vimキーバインドユーザー的にはIdeaVimの挙動のVim互換性がイマイチなのも気になるところだが、VSCodeVimやVSCode Neovimがあまりにも厳しいので、最近はIdeaVimの方がマシだなという評価になってきた。そもそもVimやNeovimを使ってしまった方が早いというのはそう。

VSCodeの不便なところ

Kotlinを書く会社をやめてRubyとCを同時にいじるCRuby開発をする会社に入社したので、仕事で使うIDEIntelliJからVSCodeにシフトしたのはごく自然なことなのだが、個人的にはJetBrainsのIDEの方がVSCodeより便利だなあと思うシーンの方が多いので、VSCodeが業界で一番人気ぽい雰囲気なのは個人的にはやや意外である。

VSCodeで一番困っているのは、エディタで改行した時の自動インデントの開始位置がかなり異常なことで、VSCodeVimはデフォルトのVSCodeのインデント挙動に従うのでこの不便をもろに受けてしまう。具体的には、以下のように空行にカーソルがある時、

def foo
  bar
[ここ]
  baz
end

僕は空行にはスペースを残さない派なのでインデントがないところに静止するが、そこから改行すると次の行でもインデントなしで始まってしまう。ここではbazと同じインデント位置から次の行を始めたいわけだが、そうならない。他にも気になる挙動がかなりいっぱいある。そこで便利なのがVSCode NeovimというVSCodeをNeovimフロントエンドとして使うプラグインなのだが、これを使うと度々NeovimとVSCodeの同期が壊れたっぽくなって不便というのはおいておいて、VSCodeVimで存在するインデントの問題は解消するものの、それとは全然違うところでNeovimとは異なる不思議なインデントの挙動をする。何故Neovimと同じ挙動をしてくれないのかよくわからないが、これが理由でVSCodeを使うのが辛くなってしまった。

IntelliJのところに書いたVimのタブに相当するものがない問題はVSCodeにも同様に存在する。これがVSCodeの辛さに拍車をかけている。VSCodeではこれはやらないと明確に宣言されているので、絶望である。

Neovimの不便なところ

この中では一番便利だと思っているが、公平性のためにも(?)、自分がNeovimに感じている不満についても書いておこうと思う。

僕はNeovimの利点の一つがターミナル上で起動してtmuxのウィンドウの1つにしたりできることだと思っていて、CUIからしか起動しないのだが、そのためターミナルが表現できるUIしか使えないという欠点がある。これまでそれほど気になることはなかったが、LSPのdiagnosticsでエラーが出るところに赤い波線ではなく文字と同じ下線しかいれられないとか、これくらいはそんなに頻繁に使わないからショートカットで効率化するんじゃなくてマウスで操作してもいいんだけどなみたいのがそもそも選択肢として存在しなくて、僕が乱暴に消費しまくっているショートカットキーと衝突している機能を使う必要が出てくる。とはいえ、いずれも大した問題ではない。

Neovimの二大LSPプラグイン

やっとLSPの話。vim-jpを眺めていると、設定の仕方が二大派閥みたいになっていて、僕は両方完全に設定を終えてみた上で片方を選ぶという風にしたので、違いについて書いておく。

nvim-lspconfig

そもそもNeovimにはビルトインのLSPクライアント nvim-lsp があるのだが、nvim-lspconfigはそれの設定だけ提供するというもの。大雑把に言うと以下のような特徴がある。

  • nvim-lspconfigがサポートしているLSPの幅が広い
  • デフォルトの設定がややイケてないので、設定に時間がかかる
    • デフォルトだとdiagnosticsがインラインで全て展開されるが、情報量多すぎて見にくいので、カーソル合わせたところだけ出すようにしたくなる (設定は可能)
    • fidget.vim いれたり lualine.nvim のカスタマイズなどで自分からprogress出すようにしないと使いにくい (設定は可能)
    • Language Serverのインストールもmason.nvimとかが必要

次の奴に比べるとこちらの方がカスタマイズが効いてVimっぽいので、Vim過激派(?)の人はこちらを好みそうだなという感じはある。

coc.nvim

それとよく対比されるものとしてcoc.nvimがある。"Make your Vim/Neovim as smart as VSCode" というキャッチコピーなのだが、これは単にLSPを使っているというよりは実際にVSCodeプラグインを移植して来ることで動いている。そのためプラグインVim側ではなくnode.js側のエコシステムで管理することになり、設定もJSONに書くところを含め、何かとVimというよりはVSCodeぽい感じの挙動をする。以下のような印象がある。

  • VSCodeでメジャーな拡張に相当するものは大体あるが、nvim-lspconfigに比べると少ない
  • あまり設定しなくてもいい感じになる
    • いい感じのポップアップUIで進捗が出たり、Language Serverのインストールもやってくれたり、最初からVSCodeぽくなっている

例えばcoc.nvimだとRubyのLanguage ServerがSolargraphしか対応してないのだが、nvim-lspconfigでいろいろ試した結果Solargraphが一番よくできていると思ったので、正直設定に時間をかける余裕がそれほどないというのもあり、coc.nvimでいいかという感じになった。

タイトルの「Neovimを一瞬でVSCode並みに便利にする」というのはどうやるかというと、つまり忙しい人はcoc.nvimを使っておけということである。nvim-lspconfigの方の設定は何行にも渡って設定が必要だったが、coc.nvimの方はインストールしておきたいプラグインの列挙とキーバインドの設定だけでほぼ使える状況になった。実際にはstatuslineに coc#status() を出したり nvim-scrollbar でdiagnosticsの分布がパッと分かるようにしてみたりしたが、definitionに飛んだりcompletion出したりするみたいな用途ではデフォルトでほぼ困らない。

ちなみにこの記事で主にVimではなくNeovimの話をしているのは、このプラグインNeovimじゃないと動かないからだ (編集: 名前の通り当初はNeovim限定だったものの、今はVimでも動くらしい *3 )。Vim 9はVim 9 Scriptを発明するみたいなことをやってるが、まあ皆Vim 9専用言語よりLuaとかNode.jsとかPythonを書きたくて、長期的にNeovimの方がエコシステムが発達していくんじゃないかと思っている。

各言語のLSP

まだcoc.nvimを使い始めて日が浅いので、直近使っている数少ないプラグインについてしか言及しないが、ここで書いてない奴も例えばGoとかはgoplsの奴使って大体VSCodeと同じになりそうだなという印象しかないので、Wikiで各言語のプラグイン名を調べてインストールするだけで特に困ることはなさそう。とはいえ、せっかくなので既に使った奴に関しては感想を残しておく。

C

coc-clangdとcoc-cclsを試したが、どっちも変わらんなと思ったのでclangdをいれるだけで良いcoc-clangdを使っている。CRubyだとclangdがfalse positiveなdiagnosticsをまあまあ出してくるが、それはVSCodeデフォルトのvscode-cpptoolsでも同じなので、まあC言語を使っているのが悪いということで諦めている。

vscode-cpptoolsに相当する奴は移植するつもりがcocに移植するつもりが今のところないらしいが、コンパイラgccを使っていようがclangを使っていようがclangdの体験は大して変わらないので、coc-clangdでよさそう。むしろvscode-cpptoolsは何か知らないけどエディタ起動するだけで勝手にconfigureとかビルド始めてビルドディレクトリを壊されるのが気になっていて、clangdに移行して良かったという感じがある。

追記: 最初書き忘れてた内容として、CはVimデフォルトのシンタックスハイライトが弱いので、coc-settings.jsonsemanticTokens.filetypes でセマンティックシンタックスハイライトを有効にすると便利。あとclangdの設定としてcompile_commands.jsonが必要なんだけど、これはbearを使って makeのかわりに bear makeとすると良い。これをやる時は1からビルドする状態でmakeを叩く必要がある。

Rust

VSCodeと同じでrust-analyzerを使う。おしまい。rust-analyzerはVSCodeでもNeovimでもファイルを保存した時に実行されるので、いくつかのdiagnosticsはエディタ上で修正しても保存をもう一度叩くまで警告されっぱなしになったりするのだが、良くも悪くもVSCodeとNeovimはこれに関しては似たような体験になる。IntelliJやCLionでは保存しなくてもdiagnosticsが直るような自然な挙動になっていた気がするが、どうもJetBrainsはrust-analyzerは一部のコードを共有しているだけで、Rust対応が基本スクラッチになっているようで、他の場所では素のrust-analyzerに比べ微妙ぽい挙動をしていた記憶 *4 があり、Rustに関してはどのエディタが特別体験が良いとかはなさそう。

Ruby

Rubyは自分で型を書く場合はSorbetSteepを使っておくと、LSPが割といい感じになるらしいのだが、僕は仕事とは別に最近CRubyの標準ライブラリを秘かに書き続けていて、ruby/rubyのトップレベルにおもむろにGemfileを置いたりするわけにはいかないので、別途型情報がなくても自明な範囲で定義ジャンプやdiagnosticsがやりたいなという気持ちがあった。

SorbetやSteepを使わない場合に関してはRubyMineが圧倒的に体験がよくて、これはLSPでは太刀打ちできない感じがあり、普通の人は基本的にRubyMineを使っておけば良いと思っている。その一方でRubyとCを両方RubyMineからいじれないという問題があるので、CRuby開発者やC拡張gemメンテナでかつ複数エディタを行ったり来たりしたくない人は、LSPで耐える必要がある。

その範囲ではSolargraphが現状一番よくできているというか、定義ジャンプに使うという用途では選択肢が実質これしかない。他のものは textDocument/definition がそもそも提供されてなかったり、それがexperimentalになっていて有効化しても起動時に壊れたり、解析対象がものすごく小さくないと動かなかったりする。SolargraphはSolargraphでまあまあ対応してないシンタックスがあって、じゃあと思ってPR送っても割とPR来てもマージしてなさそうな雰囲気だったりとか、それができなければSolargraphに忖度したコード () を書くはめになったりとか、RBSも未対応だとか、かなり先が長い感じがする。同僚やr7kamuraさんとかがその辺に対応した別のものを開発しそうな気配を感じており、応援している。

Rubyは自分がコミッターをやっているのもあってIDEなくても書けるやろみたいな慢心をしていた節があり、RBSで型付けをしたりLSPを使って開発体験向上みたいなのもつい最近までほとんど興味がなかったのだが、実際に使ってみると、今のSolargraphのクオリティのものでもかなり開発効率が上がったように感じる。一方でSorbetやSteep以外のLSPの現状最高の体験がこれかあ、というのは他の言語に比べると相当遅れている印象なので、このあたりがRuby 3の注力分野の一つになっているのはとてもいいことだと思った。

DAP

デバッガもVSCodeのCodeLLDBみたいな奴使いたいんだよなーと思って調べたところ、vimspectorというのを使うとVSCodeのデバッガ拡張をNeovimに使えるらしい。というのも、LSPみたいな感じでMicrosoftDAP (Debug Adapter Protocol)というものを提唱しているようで、coc.nvimとvimspectorを使うと、何かVSCodeの拡張は大体Neovimでも使えそうだなという雰囲気がある。まだこれは試せてないのでまた今度。

まとめ

coc.nvimをいれてここからプラグインを探して使うだけで割とVSCodeみたいな体験になる。

*1:https://www.jetbrains.com/help/idea/discover-intellij-idea.html に "C/C++ are not officially supported in IntelliJ IDEA, but you can use CLion" と書いてある

*2:Kotlinに関しては同じ会社が作っている以上は、JetBrainsが作っているIDEが一番充実しているという状態は揺るがないと思う

*3:ycinoさんに教わりました、感謝。一方、最初Neovimにしか対応してなかったことからも、この段落で言ってることは依然としてそれほど外してないように思うので、そのまま残した。

*4:unused importの警告がないとかだったような気がするけど、うろおぼえ。それは最新版では直ってたりするかも

Zigで簡単クロスコンパイル 2022

僕は以下の3つのツールを複数プラットフォーム向けにクロスコンパイルしてバイナリ配布しており、以下のように全て異なる言語で開発している。

ロスコンパイルに苦労している話をするとZigを使ってみたらいいんじゃないかと言われることがあり、周りでもZigが何となく流行り始めた気がするので、これらのツールに実際自分で使ってみてどうだったかという事例を紹介したい。

Zigとは

Zigはそもそもプログラミング言語なのだが、C/C++とのinteropがやりやすい言語なようで、おそらくそれに必要でLLVMベースのC/C++ツールチェインが同梱されていて、しかもそれをDrop-In Replacement for GCC/Clangとして売りにしている。

僕はZig言語そのものにはそれほど興味はないのだが、クロスコンパイラとしての zig cc には強い興味があるので、この記事はその話だけする。

使い方

Go

そもそも前提として、Goは普通は以下のようにするだけでクロスコンパイルができる。

CGO_ENABLED=1 GOOS=[GOOS] GOARCH=[GOARCH] go build

問題はCのコードを連携するためにcgoを使う時で、本来cgoは避けるのが賢明なのだが、sqldefでPostgreSQLのパーサーを自分でメンテするのが大変になってきたので本家PostgreSQLのCのコードを連携できるライブラリを使うことにしたため、cgoが必要になってしまった。

一方、Zigを使ってクロスコンパイルするのは簡単で、上記の環境変数の他に、以下の環境変数を足して go build してやれば良い。target名は zig targets で調べられる。

CC="zig cc -target [target]"

GitHub Actions上でのZigのセットアップが簡単で、targetを設定しなくても使えるのは便利 *1

macOSでは動かない

問題なのはmacOSをターゲットにする場合で、MacOSX.sdkを自分で調達 *2 してきた上でこの記事に書いてあるように複雑なフラグを渡さないといけないのだが、そうしてがんばってリンクを成功させても、実行してみるとruntime.cgocallでクラッシュしてしまう。元々macOS向けのZigとcgoの相性はあまり良くなく、色々試したがこれを直すのは無理そうだなと結論づけた。

macOS向けのクロスコンパイルにはosxcrossというツールがあり、MacOSX.sdkを調達した後これを使ってclangクロスコンパイラをビルドしそれをCCに指定するとクラッシュしなくなった。

実はXcode 12.2+は元々クロスコンパイルに対応しているので、GitHub Actionsでmacos-latestを使うと、CCに何も指定しなくてもarm64向けのcgoクロスコンパイルができることをその後vim-jpで教わり、そのようにした。現状macOS向けのクロスコンパイルはこれが一番簡単そう。

Rust

Goはlibcにあたる部分も自前で書いているためcgoを使わない限りはクロスコンパイルが通りやすいのだが、Goとは違ってRustは普通にビルドするとlibcへの依存が発生するため、自分ではネイティブ環境への変な依存を作っていないつもりでもstaticなバイナリの作り方が自明ではなく、クロスコンパイルも通しにくかったりする。

"Just Work" してくれない

Zig Makes Rust Cross-compilation Just Work という記事があり、題名の通りZigを使うとRustのクロスコンパイルがやりやすくなるそうなので、やってみた。しかし、実際にはglibcを使う場合もmusl-libcを使う場合もlibcに関係するシンボルがconflictしてしまう。この問題はRust + zig cc CRT conflict.というスレで解説されているが、先ほどの記事でうまくいってるのはlibcがダイナミックリンクされるmacOSを対象にクロスコンパイルしているからで、LinuxWindowsだとそうならないためZigが定義するシンボルと衝突するらしい。

cross

仕方ないのでcrossという既存のクロスコンパイルツールを使ったらすんなり動いたので、xremapはcrossを使うことにした。以下のようにするだけなので簡単。

cargo install cross
cross build --target=[target]

cargo-zigbuild

その後rust-lang-jpでcargo-zigbuildというのを教わった。これを使えばZigを使ったクロスコンパイルもうまくいくかもしれない。わざわざcrossから移行するモチベーションはないが、次クロスコンパイルを新たに設定する時には試してみようと思っている。

mruby

mrubyはよく使うライブラリが大体Cのコードに依存しており、唯一のクロスコンパイルツールチェインも5年前にメンテがストップしているので、mrubyのクロスコンパイルは地獄が約束されている。クロスコンパイル用の設定のAPIはあるのだが、そこに渡すクロスコンパイラは自分で調達しなければならないからだ。

そこでZigの出番である。良くも悪くもmrubyはCとの親和性が高いというか、単にCのコードとCで書かれたVMで動くmrubyのバイトコードの集まりなので、Cのクロスコンパイラを渡すインターフェースはGoやRustより充実している。以下のように設定すると動く。

MRuby::CrossBuild.new('[target]') do |conf|
  [conf.cc, conf.linker].each do |cc|
    cc.command = 'zig cc -target [target]'
  end
  conf.archiver.command = 'zig ar'

  # mrbgems/mruby-yaml や mattn/mruby-onig-regexp にはこれも必要
  conf.host_target = '[target]'
end

mitamaeでは元々dockcrossを使ってWindowsLinuxのバイナリをクロスコンパイルし、osxcrossを使ってmacOSのバイナリをクロスコンパイルしていたのだが、前者はDockerコンテナのメンテ、後者はMacOSX.sdkの調達が面倒だったので、今回の変更でZigをいれるだけで動くようになったのは便利。GoやRustに比べ、mrubyと一緒に使う方が親和性が高く感じた。

macOSではzig ranlibの指定が必要

一つだけ注意点としては、macOS向けのビルドはranlibをzig ranlibに差し替えないと動かない感じがしており、ranlibを指定するAPIがmrubyになさそうなので、 ENV['RANLIB'] ||= 'zig ranlib' などで無理やり子プロセスに渡るようにしておく必要がある。この設定はどのtargetでも動くので、そこまで困りはしなさそう。

まとめ

動く環境が限られていたり、特定の言語に向けて設計されたツールと違って連携方法が自明ではなかったりするので、現時点ではそれほど使いやすくはないというのが正直なところ。

一方、どれも解決は可能な問題に見えるし、実際過去に他の言語のツールに修正を取り込ませている様子も見えるので、今後便利になると期待している。

*1:デフォルトのバージョンだとcgoと連携する時にバグがあって動かないので、今は明示的に新しいZigのバージョンを指定する必要があることに注意。それから、Zigに対応するためにはGo側も1.18以上にしないといけない https://github.com/golang/go/issues/43078

*2:https://github.com/phracker/MacOSX-SDKs が便利

Treasure Data を退職しました

約5年5か月働いたTreasure Dataを7/22に退職した。7/25からShopifyに入社し、RustでJITコンパイラを開発してRubyを高速化する仕事をする。

仕事としてやりたい分野が変わってきて自分は今回転職したけど、とても良い会社なので、この記事がTreasure Data (以下TD) で働くことに興味がある人の参考になれば良いと思っている。*1

5年勤続記念にいただいたトロフィー

やっていたこと

APIチーム

元々TDにはJavaで分散システムを書きたくて入社したのだが、TD入社前に特にそういう経験があるわけでもなく主にRailsをやっていたこともあり、Railsでプラットフォームを開発するチームに入った。基盤開発をやりたいと思いながらサービス開発者として最初働き、後に基盤開発チームにジョインするみたいな過去の経験があったので、今回もそういう感じでいけると考えていた。実際このチームには最初の1年だけ所属した後、次のチームに移った。

現状APIチームにいる人の誰よりもそのリポジトリにコミットしている程度にはその短い期間で色々書いたのだが、おそらく同僚の記憶に残っている仕事は、分散モノリスっぽい設計になっていたせいで障害の温床になっていたリポジトリコンポーネント境界を動かし、適切にマイクロサービスとして独立させたことだと思う。この仕事についてはRailsDM 2018でも紹介した

ちなみにTDはRails内からJavaScriptフロントエンドを扱わず、完全別リポジトリで別チームが開発する体制*2なのだが、自分は個人でReactやReduxを使っていたのもあり、自分で書いたAPIを呼ぶコンソールを自分で直しに行くこともあった。

TDは全然違うチームのプロジェクトに突発的に参加することも割と行なわれていて、例えば「来週からアメリカに飛んでこれ作ってきて」と当時CTOの太田さんに言われて弾丸で@mururururuさんとFluentd関連のGolang製プロダクトとそのUIを書いたり、@tagomorisさんがリードしていたJavaで分散システムを書くプロジェクトに入れていただいたりと、色々面白いことができた。

SREチーム

インフラが創業時からあまり変更されておらずデプロイ周りで開発効率があまりにも悪いことが入社時から気になっていて、そのあたりをどうにかする仕事も片手間にやっていたのだが、それを本格的にどうにかしてくれる人を採用できなさそうな雰囲気だったので、SREチームに1年だけ転籍して自分がどうにかすることになった。

元々どうなっていたかというと、cronで30分おきにChefが実行され、しかもランダムで失敗するので全台デプロイに最悪数時間かかり、各インスタンスsshすることでデプロイ完了を確認するという感じだった。前の会社の基盤チームで開発していたデプロイ環境があまりにも快適だったため、あまりにも失望が大きく、これに近いものをTDにも作ろうと考えていた。

SREチームは元々AWS CodeDeployを使うための環境をローカルからAnsibleでプロビジョニングする感じで新ツールを作っていたのだが、使いやすさに色々不満があり僕がAWS Lambda上にそのスーパーセットとなるAPIPythonで書き直した。これでSlackからもwebhookで呼び出せ、インフラの差分更新が細かくできるようにして、今日ではほとんどの開発者に利用されている。*3

基盤を整えた後はChefレシピをmitamae化するなどでせっせと新基盤に移行し、負荷が高いクラスタのオートスケールを実現したり、Ubuntuのバージョン上げたりDocker化したりした時にRailsアプリが遅くなったのをどうにかしたりとかした。

Backendチーム

3年目には、当初から入りたかったBackendチームに入ることができた。Backendには4つのサブチームがあり、そのうち主にPlazmaDBというTD内製のストレージレイヤーを開発するStorageチームに所属し、3年半くらい働いた。

TDではHadoop、Presto、FlinkなどのJavaフレームワークを扱うことが多く、そのためバックエンドではJVM互換言語が使われていることが多い。昔は大体Java、その後Scalaがクエリエンジンチームで流行り、僕がBackendチームに入るころにはKotlinが採用されていて、Backendが作ったサービスのほとんどは今ではKotlinになっている。

僕はTDのメインのRailsアプリからストレージ関係の機能をマイクロサービスとして切り出す仕事をした後、そのサービスをベースにカラムレベルのアクセスコントロールをプラットフォーム全体に適用可能にするプロジェクトを1年くらいリードし、あとはPlazmaDBのストレージを最適化するワーカーを書いたり、クエリを最適化するための統計を提供するような仕事をした。

APIチームでご飯を食べに行った時、@kamipoさんにBackendに移ったら何をやりたいか聞かれて、ストレージ周りをやりたいという話をした記憶があるが、実際その時想像していたような仕事が最後の方はやれていたように思う。

どんな会社なのか

OSSで活躍している人が多い

MessagePack, Fluentd, Embulk, Digdagを生み出した古橋さんを始めとして、GitHubで数百、数千のスターを集める人気リポジトリの作者が多い。Rubyはここ何年か@nalshさんがリリースマネージャをしているし、今もRubyコミッタは4人、Railsコミッタも1人いる。TDの人が作っている何らかのOSSにお世話になっている人は多いのではないだろうか。

僕も古橋さんみたいにTDの仕事をきっかけに広く使われるOSSを生み出したいという野望があったが、多分一番うまくいったのは、@tagomorisさんのプロジェクト下でJavaでサービスを書きながらRidgepoleのRuby DSLスキーマ管理をしていたミスマッチ感から思いついたsqldefで、これはありがたいことにいろんな会社で使われている雰囲気を感じる。あとはrspec-openapiも仕事中に思いついたもので、これもちょっと使われていそう。

エンジニアがお金を稼ぎやすい

CEOの太田さんが元々エンジニアで技術力も高く、またTDのビジネスのコアに自社製、他社製問わずOSSが使われていることから、エンジニアリングの重要性や難しさを経営陣が深く理解している組織であると思う。その上、TDに入ったエンジニアを全員キャッシュリッチにしたいという話を太田さんは以前していた。

TDでは、普段良い仕事をしている人たちは、会社がうまくいった時にドカンとお金をもらえている雰囲気がある。TDがArmに買収されたころ短冊に一億円と書いたりSoftBankの下で再出発となったころは二億円と書いたりしたが、CEOやCTOもこれを見て本気にしてくれるし、いずれもがんばれば現実となるような機会や裁量が与えられていた。転職でこのチャンスを逃すことは残念である。

大規模データの分散処理に挑戦できる

TDはエンタープライズなお客様にフォーカスしてプロダクトを作っているため、TD自体の会社のサイズは大きくなくとも、大規模なデータを持つお客様を何社も引き受けることになるので、それをマルチテナントで捌いて性能を出すことが求められる。

分散DBの性能でGoogleAmazonと全面的に戦う、というような開発投資はしていないが、自分たちのお客様の用途に特化した性能改善は盛んに行なわれており、分散DBの最適化みたいな面白い仕事ができる。単に分散DBそのものを売るよりは、それを活用した周辺ツールとの統合的な体験で価値を生み出すビジネスをしているため、何を最適化するとどうビジネスにインパクトがあるかわかる面白さもある。

クックパッドのデータ活用基盤をTDからRedshiftに移行した青木峰郎さんが今はTDに所属しているおり、日々楽しそうな仕事をしていることも書いておきたい。

英語や海外移住に挑戦しやすい

日本人が多いので英語話者が日本人の英語アクセントに慣れているだけでなく、人数が多い分英語力も様々であるため、英会話を勉強中の人への許容度が高いように見える。もちろん入社面接では多少英語を話せる必要があるが、それさえ突破してしまうと、無料で英会話レッスンを受ける機会がよく設けられてるし、単純に英語ミーティングの機会が増えるとそのうち慣れる。

僕自身、東京オフィスからマウンテンビューオフィスに移籍した組なのだが、どうしても移住がビジネスに必要みたいな状況ではなくとも、タイムゾーン間のバランス調整や知見共有みたいな名目で希望者が時おり北米*4へ移住していたりする。その際のビザのサポートは会社がやってくれて、初めてのUSビザもグリーンカードも全てTDのサポートで取得させていただいた。

今後やりたいこと

言語処理系キャリアを築く

僕はこれまで分散システムと言語処理系の2つの技術に主に興味があった。学士論文も分散システムのモデル検査のための言語のコンパイラを書くものだったので両方に関係している。学部卒業後は仕事で分散システムの開発をしつつ、個人の時間で様々な言語処理系を書く形で両方の分野に常に触れていた。

社会人を続けながら大学院で勉強し、どちらに関しても複数の授業を取った結果、いずれも人並以上には好きそうだが、最もこだわりがあるのは言語処理系の方であることがわかってきた。その結果、子供が産まれてから仕事以外に使える時間が短くなって必然的に言語処理系に使える時間の比率が下がっていくことにややストレスを感じるようになり、一番興味のある言語処理系の方を仕事にしてそれ一本に集中するのが幸せなのではないかと思うようになり、転職した。

言語処理系の開発がそれ自体でお金を生むのは難しく、日本ではそういう仕事はかなり限られてそうに思うが、アメリカで求人を眺めているとまあまあ面白そうな選択肢があるし、特にシリコンバレー在住で採用してもらう場合は、日本に住んでたら考えられないような待遇が得られる*5。片働きで子供を養うことを考えると、これは僕にとっては実質シリコンバレーに来たことで可能になったキャリアと言える。今回のポジションを可能にしたShopifyにもとても感謝している。

3億円貯める

僕はアメリカに出稼ぎに来ていて、さっさと3億円貯めてリタイアしたいという話はRubyist Hotlinksでのインタビューで2年前から公言している。この意思は今も変わっていないのだが、妻も僕も主に食が理由でなるべく早く日本に帰りたいという気持ちがあり、あと10年くらい働いた後、子供の学校とかの区切りが良くなったタイミングで日本に帰ろうと思っている。

流石にここから10年で資産3億円に達する自信はないのだが、総資産が $2M (約2.7億円) 以上あるとグリーンカードを放棄する時に総資産の2割にあたる額を課税されるという話があり、$2M に達する前に帰った方がお得という感じもしており、まあなんか結構稼いだなみたいなところで帰ろうかなという感じ。

ICとして更に昇進する

仕事というのはお金を稼ぐためにやっていることなのでお金は大事だが、一方でそれだけを追求するとメンタルがやられて持続性がなくなるので、TDでは僕は50%の時間を会社の売上や自分の昇進に最適化し、残り50%を自分が技術的に興味のある仕事をやる方に最適化することでバランスを取りながら働いていた。

その前者の50%にあたる努力の過程で、昇進のために上司と相談した結果、上司は僕の技術的なスキルには特に不満がなく、かわりに大きなプロジェクトのリードや他チームとの調整をこなしたり他のエンジニアを成長させたりする能力を示すことが求められたため、ここ2年くらいは割とそのような業務の機会をいただくことが多くなった。自分のコミュニケーション能力は特に強みではないと思っているのだが、実際はやってみると周りからの評価が上がったように見えた。

これは、自分が得た技術的な知識を自分の仕事に活用するだけでは会社やビジネスに与えるインパクトに限りがあり、他の人も自分の能力を活用して仕事がしやすくなるようにすることで、低い労力で大きな成果を生み出すチャンスになるということだと考えている。少し前に@__gfx__さんのICに関する記事が話題になったが、僕はICというのは生涯現役でコードを書くという側面よりは、昇進するにつれむしろそれ以外のスキルが重要になるキャリアパスだと受け止めている。

ICとして昇進するというのは、つまり自分が会社に大きなインパクトを与える能力をつけることだと思っていて、たくさんの利益を生む大きな組織でもそれができるようになれば、仮に自分が直接売上を立てない部門にいても、いっぱいお金をもらう経営的妥当性ができるので収入に直結するため、さっさと3億円貯めて日本で自由に生きるためにもがんばっていきたいと思う。

*1:事実、自分の退職が確定してから退職するまでの間に、転職したがっている友人をリファラルでいれようかと試みたりした。自分にリファラルボーナスが入らなくてもおすすめしたいほど良い会社ということ。

*2:Railsのフロントエンド周りは常にわちゃわちゃしているので、それに影響を受けない設計であったのは何かと便利だったと思う

*3:一方で、これは短期的に目的を実現するために考えたアーキテクチャなので、長期的にはコンテナベースのデプロイに移行したりもっとコミュニティベースの実装を利用できるように変えた方が良さそうだなあと何度か声を上げていて、2022年の現在では本格的にサービスのデプロイをEKS移行するプロジェクトが動いている。

*4:アメリカのマウンテンビューか、カナダのバンクーバー。最近はバンクーバーに移住する人の方が多い。

*5:といっても、無からお金は生まれないので、自分がどのように会社やビジネスにインパクトを与えられているかは常に考え続ける必要があると思う。

後悔しているがやめられない開発効率向上術

僕はdotfiles系リポジトリ*1のコミット数を合計するだけで2261コミットある、.vimrcばっかりいじっていて開発が全然進まないタイプの人間で、つまり開発環境にとてもこだわりがある。

こだわりすぎて他に誰もやってなさそうな数々のカスタマイズを生み出してしまったが、やらなければよかったと後悔しているものが多くあるので、僕のような人が新たに生まれないよう、やめておけばよかったテクニックとその法則のようなものを紹介したい。

後悔しているもの

C-h, C-y, C-u, C-oでウィンドウ切り替え

Windows, macOS, Linux問わず以下のグローバルなキーバインドを設定している。

  • C-h: ターミナルにウィンドウ切り替え
  • C-y: IntelliJかCLionにウィンドウ切り替え
  • C-u: Google Chromeにウィンドウ切り替え
  • C-o: TwitterかSlackにウィンドウ切り替え

Vimはターミナル内で起動しており、コードを書いている間基本的に上記4つのウィンドウだけで生活するようにしている。 macOSでいうCommand+Tabみたいなショートカットでウィンドウを切り替える場合、まずそれを押してウィンドウがどういう順番で並んでいるか確認し、 その後目的のウィンドウにカーソルが辿りつくまで何度か同じキーを押す必要があり、2アクション以上必要になるが、 このショートカットがあると常に一瞬で目的のウィンドウを開くことができる。

何年もこれを使い続けた結果もうやめられなくなっているが、まず (シェルとかで使える) C-uみたいなちょっと便利な機能を潰しているのが困る。ペアプロ相手がC-uを使おうとしてブラウザが開いてびっくりされたことがある。また、見てわかる通りものすごく押しやすいキーバインドを消費しているため、ここに新たに他のウィンドウのショートカットを足そうとすると、似たような押しやすいショートカットを捨てることになる。これは大変だし、そもそもこのショートカットの数が増えると脳が混乱しそうなのでスケールしない。それと、何か新しいデスクトップアプリを使う必要が出てくる度に、諦めるか、ウィンドウ切り替えで不快な思いをすることになる。

対案としては、Slackのワークスペースを切り替えるのと似た感じでCtrl+1, Ctrl+2, ... みたいなもう少しコンフリクトしにくくスケールもしそうな割り当てにするか、まあそもそもこんな方法で生産性向上するのは諦めて大人しくCommand+Tabを使うというのが考えられる (やらなそう)。

半透明背景エディタ

これも全OS共通で、ターミナルの背景は半透明にしている。これは多分学生のころ見た目がかっこいいと思って始めたのだが、実用的なメリットとして、ターミナルを全画面表示にしていてもその裏側のブラウザやSlackに書いてある内容が読めるというものがある。で、気付くとこれに依存した生活をしてしまっていて、Vimもターミナルで起動しているためコードを書いている時もブラウザのドキュメントを透し見する癖がついたが、JetBrains IDEなどの背景が半透明化できないエディタで困ることになった。

Linuxではウィンドウを丸ごと半透明化するのは簡単なのだが、ウィンドウ全体を半透明化するのと背景だけ半透明化するのでは読みやすさが全然違うので話にならないし、macOSだとそもそもそれができるツールはOSのバージョンが上がるにつれ動かなくなったりしていった。それから、このウィンドウを重ねて見る生活はタイリングウィンドウマネージャでは実質不可能なことが多く、そういうウィンドウマネージャを選択肢から外すことになる。

デュアルディスプレイはディスプレイ間のマウスカーソルの移動が個人的になんとなく不快なのでいつもシングルディスプレイで作業をしているのだが、対案としては、ワイドディスプレイを使うようにして単にウィンドウを左右に並べるのがよさそうと思っているが、ケチなのでなかなかディスプレイが買えていない。

親指修飾キー

僕のキーボードの修飾キーは以下のような配置にして、全て親指で押している。

 [ C  ][ V  ][ B  ][ N  ][ M  ][ ,   ]
  [Ctrl][    Space    ][Shift][ Cmd ]

JISのHHKBという、スペースキーがトップクラスに短いキーボードを使っているため、これらの修飾キー全てがとても押しやすい。 何故こうしているかというと、Ctrlは元々Aの左で小指で押していたのだが、Emacsを使っていた時期にこれで小指が痛くなりまくったので、再発防止策としてVimに移行したが、それでもシェルやVim以外の場所でEmacsキーバインドを多用していたため、Ctrlを親指で押すようにしたら指が痛くなることがほとんどなくなった。あとSKKを使うようになってからShiftキーを多用するようになったが、これも小指が痛くなったので、親指で押すようにした。昔はSandS *2 を使っていたが、暴発が多いのでShiftキーは独立させている。

これ自体には後悔はないどころか、長くプログラマを続けるために指の負担を減らすことはとても大切だと思っているが、以下の制約がつくため間接的に後ろめたい気持ちがある。

JISキーボード

親指修飾キーはキーボードがUS配列だととても大変である。上記のキー配置はJIS配のHHKBのものだが、US配列のHHKBはこうなっている。

 [ C  ][ V  ][ B  ][ N  ][ M  ][ ,   ]
[             Space                ]

これは特に誇張とかなく本当にこうなっている。つまり、親指を軽く曲げて届く位置に一切修飾キーがない。大体スペース押すのにこんな広い範囲を使い分けるわけないんだから、スペースの無駄遣い*3である。

JISキーボードを使っていて何が困るかというと、僕はUSに住んでいるのだが、JIS配列のキーボードが居住国で買えなくなる。JIS配列のHHKBを買うために5000円くらい送料をかけてHHKBを買ったことがあるが、開封直後買い間違い*4に気付き、PFU開封したら絶対に返品を受けつけないため、もう一度5000円の送料をかけて別のモデルを買うはめになった。それから、USの会社ではJIS配列のMacBookを貸与してくれなかったり、対応していても注文から発送までにものすごく時間がかかったりする。

指を痛めるような選択は取れないので、これは今のところどうしようもない。歯を食いしばって法外な送料を払い、返品拒否にも耐え、カンファレンス会場やオンコールなどで外部キーボードを持ち運びたくないがUS配列のMacBookが貸与されている場合は、生産性を落とし指を痛めつつ作業することを覚悟しないといけない。

C-cによるVimのインサートモード抜け

C-cはご存知の通りSIGINTを送るショートカットであるが、Vimでインサートモードにいる時にC-cを使うと、何故かインサートモードを抜けてくれる。EscはAの左に配置していて、これでもまあまあ押しやすいし基本的にはそっちを使っているのだが、上記のような修飾キー配置をしていると、現在の指の置き場次第ではC-cがEscよりも押しやすくなってしまう。それで、気付かないうちにEscではなくC-cをたまに使うようになってしまった。実際には Esc や C-[ で抜けるのとは違う挙動になるため、C-cでインサートモードを抜けるのは行儀が悪いだけでなく機能的な不便もある。Pythonを使って実装されたVimプラグインを使うと、プラグインが動いている間にC-cすると例外が発生してVimがエラーになったりする。

まあ普通にEsc使えで終わりなのだが、VimでC-cを使って困る状況を意識的に増やさないとなかなか矯正されないかもしれない。

Vimでしか設定できないキーバインド

Vimでは現在のモードに応じてキーバインドを設定できる。インサートモード以外では任意の文字を打ち込む必要がなくなるため、いくつかの普通のキーが何も使われずにおいてある状態になる。従って、スペースキーやセミコロンなどの大変押しやすいキーをプレフィクスキーにすることができ、具体的には ;u でUnite.vimを開いたり、スペース→Tで新しいタブを開いたりしている。これで何が困るかというと、Vimの外で生活する時にそれとキーバインドを揃えることがとても難しくなる。IntelliJのIdeaVimだと.ideavimrcで似たような設定ができるのだが、IdeaVimが効かないモーダルが開くとそこでは.ideavimrcの設定が使えないので、Vim以外でVimと同じ操作感を再現するのが困難になってしまう。

対案としては、何かキーバインドを設定するときはVimでしか設定できなそうなものを使うのではなく、普通に修飾キーを組み合わせ、モードに依存しないショートカットにするのが良い。

エディタの垂直分割

VimIntelliJのIdeaVimで:vsし、左右にソースを並べてコードを書くことが結構あるのだが、画面を分割した時の挙動がエディタによって異なるため操作感がかなり変わるのが結構困る。というか、画面を分割した時のIntelliJ側の挙動が圧倒的に不便で、垂直分割した後左で関数定義にジャンプする時に左で新たなウィンドウが開くのではなく、右側に同じファイルが開き済みの場合何故か右の画面が遷移してしまい、右に何かを出しっぱなしにして左でコードを書きたいみたいな時に大変不便。

そもそもVimだけ使う生活に戻すか、あるいは今IntelliJで書いているものは全て別のエディタ、例えばVSCodeで書くように変えようかなとか考えている*5

7/21 追記: @ka2n さんから "When navigating to a file prefer selecting existing tab in inactive split pane" をオフにするというテクを教わり、これで上述の不満は解消されることがわかった。ただこれが解消されても、Vimだとタブごとにペイン分割、IntelliJだとペインごとにタブ分割となる違いは依然として気になっていて、Vimの方が挙動的には便利だと思っているが、UI的にはIntelliJの方が自然なので、どうしようもないかもしれない。

後悔していないもの

Emacsキーバインド

矢印キーはホームポジションから遠いことが多いので、少なくともその点において、Emacsを使わなくなった今でもEmacsキーバインドは重宝している。 Emacsの C-何とか のキーバインドを奪ってくる不届き者のWebサイトも結構あるのだが、大体キーリマッパ側で矢印キーにリマップしてしまうなどの方法で不便を解消できることが多い。同様にC-a/C-eをHome/Endにリマップしたりするが、これらが微妙に違う挙動をするのは気にならないこともない*6のだが、まあ耐えられる範囲。

逆にC-x C-sみたいなキーシーケンスとか、マーク機能を利用したリマップに頼るのは、キーリマッパへの依存度が高くなりすぎるのでやめた方がいいだろうと思っていて、やっていない。

ちなみにmacOSは他のOSだとCtrlなショートカットがCommandキーに分離されているからEmacsキーバインドが使いやすく、WindowsLinuxではそれができないので不便みたいなことを言う人がいるが、Commandキーみたいなものはキーリマッパを使えばいくらでも生み出せるので、そういう人は単にエアプか、キーリマッパでも衝突回避しにくい深淵な使い方をしているかのどちらかだと思う。

非分割キーボード

今現在はノートPCもJIS配列なのだが、外部キーボードとノートPCについてるキーボードがおおむね配列が同じだと、外でノートPCだけで作業する時に操作感が大体同じになってとても便利。分割方法にもよるが、これはErgoDoxとかKinesisみたいな特殊な配列をしている分割キーボード*7だと、親指周りの操作感が変わってしまってノートPC単体での作業をするとき不便になる。

tmux

ターミナルで複数ウィンドウ・複数タブを使うかわりにtmuxの複数セッション・複数ウィンドウを利用している。個人的にはうっかりターミナルを閉じてもシェルのセッションが保たれる利点にはあまり依存してないのだが、どのOSでも操作感やUIが統一でき、画面の分割も簡単で、コピーモードを使って画面上のどのテキストもキーボード操作だけでコピーできるのがとても便利だと感じている。

SKK

普通のIMEのかわりにSKKを使うことで編集効率が上がっているかというとどうなのか何ともいえないが、SKKの操作感はVimキーバインドのような気持ちよさが少なくともある。これは他の人のPCを使う時に一見困りそうだが、意外と頭の切り替えがうまくいくし、そこでガッツリ何かを書かないといけないことはほぼないので、後悔することは少ない。ibus-skkAquaSKK、CorvusSKKを使っているが、どれもほぼ同じように操作できるので、移植性はむしろ高い。ibus-skkが全然メンテされてないのは気になるが、Linuxで使える別実装はいくらでもあるので致命的ではない*8

まとめ

要するに大切なのは移植性である。OSやエディタを変えても動く設定を使うのが望ましい。そもそも設定しなくても使えて、PCを初期化したり他の人のPCを使ったりしている時でも可能な操作をするのが理想的。

*1:https://github.com/k0kubun/dotfileshttps://github.com/k0kubun/legacy-dotfiles

*2:Space単押しはSpace、長押しでShiftになる特殊なキーバインド

*3:pun intended

*4:Type-Sを買おうと思ってたらType-Sではなかった。非Type-Sはうるさすぎて子供が寝ている時に使いづらいので、買い直した

*5:VSCodeにこの分割した時の問題があるかどうかはまだ検証できてないので、そうなっていればいいなという希望に過ぎない

*6:物理行頭/末と論理行頭/末の違い

*7:どちらも過去に使用していた

*8:それでもibus-skkを使っているのは、fctix-skkは挙動が遅いと感じるため

働きながらアメリカの大学院でCS修士号を取った

4年前に会社の福利厚生を使ってスタンフォードの授業を取ってみたら面白く、 働きながらでも続けられそうだなという実感を得たので、 2年後、受験を経てジョージア工科大学にリモートで通い始めた。 そして先日、ジョージア工科大学からコンピュータサイエンス修士号をいただくことができた。 画像の学位記は卒業式イベント用の非公式のもので、1~2か月すると Masterとちゃんと書いてある本物が来るらしい *1

興味あるしいつかは習得したいんだけどなかなか触る機会がない分野を勉強するついでに、アメリカでは何かと役に立つ *2 学位がもらえ、学費は会社の福利厚生でカバーされたし、 世界ランキング 45位 の良い大学を2年かからずに卒業できたので良いことづくめだったように思う。

この記事では、働きながらコンピュータサイエンスをリモートで学ぶ体験の感想や、授業の面白かった点などをまとめておく。 なお、ジョージア工科大学にも当然ながら普通にキャンパスに通う生徒がいるが、 この記事では本学のCSオンライン受講プログラムOMSCSの話だけ書く。

在学期間

2020秋入学で2022春卒業の計5学期を大学院で過ごした。 生徒だった期間は1年9か月なので、普通に2年かけて修士を取る人たちより少し短い期間で学位を取得できたことになる。

卒業には10個の授業を取る必要がある。1年に3つの学期があり、春と秋は2つ、夏は1つしか授業を取れないのだが、4つ授業を取った後に成績が良ければ各学期もう1つ授業を追加できるようになる。従って、元々の枠をフルに使い続けるとちょうど2年、6学期で卒業でき、この追加枠を使うと最短5学期で卒業することができる。 *3

最初の秋学期は子供が産まれた直後 *4 だったので様子見で1つしか取らなかったが、翌年春2つ取ってみてもそれほど大変さは変わらないなと思った *5 ので、夏に4つ目の授業を取った後は同時に3つ取る学期を2回過ごして卒業要件を満たした。

学費

各学期 $301 かかり、それに加えて各授業 $540 かかる。なので、5学期で10個授業を取ると $6905 で卒業できることになる。

これはとんでもなく安い。 スタンフォードで授業を取った 時は5単位の授業を1つ取るのに $6300 かかり、卒業にはその9倍の単位を取る必要があるが、 ジョージア工科大学はスタンフォードの授業1.1個分の額で卒業できてしまうことになる。

アメリカの無料オンライン大学 University of People という記事を年末見かけたが、これは授業料は無料だが期末試験の受講にトータル $4000 かかるというスキームらしいので、 つまりジョージア工科大学は"無料"の1.7倍しか費用がかからないことになる。 これは学士のコースの話らしい(コメントで気付いた)ので3.4倍と言う方がフェアかもしれない。

英語

僕は4年前に受けたTOEICが845点で、TOEICの点数を公言している友達が大体900点台後半なので英語のリーディングとリスニングはどちらかというと自信がない。 一方で、入学した時の記事TOEFL iBTが「102点でどの程度授業についていけているかを知りたい」というブコメがあったが、授業を聴く時も、教科書や論文を読む時も、グループ課題で他の生徒と話す時も、別にそこで苦労したことはなかった。むしろ、割とゆっくり丁寧に話してくれる先生が多いため、授業を1.2〜1.5倍速で再生していることがほとんどだった。

これは単に、コンピューターサイエンスに関する話であれば単語は大体知っていて、内容も文脈から推測しやすくなるので、日常英会話とかに比べたら簡単になるという現象な気がする。

授業の感想

CS6291 Embedded Software Optimization

組み込みシステムの最適化。コンパイラの授業と同じ先生がやっている。 僕はコンパイラの中だとバックエンドにしかほぼ興味がなく、この授業はコンパイラの授業のバックエンド特化版であるという評判を見て、コンパイラの方ではなくこっちを取ったのだった。 後に結局コンパイラの方も取ったのだが、レジスタ割付はどちらの授業でもやるものの、命令パイプライニングや分岐予測を考慮した命令のスケジューリングに関して議論されるのはこちらだけなので、その評判は間違ってはいない。ただ、僕の感覚では、コンパイラをまるごと作った方がやっぱり面白いなと感じた。この授業ではレジスタ割付の課題はどのオペランドをどのレジスタに割り当てるかを決めたら終わりだが、コード生成してベンチマークが改善するのを眺める方がよっぽど楽しめる。

CS6200 Graduate Intro to Operating Systems

修士向けOS入門。学部の時にOSの授業を取りたいと思いつつもいろいろな事情 *6 があって取らなかったのだが、この機会にちゃんと基本を抑えておきたいと思って取った。プロセス、スケジューラ、スレッド、メモリ、IOといったそれっぽい話題に大体触れる。OMSCSにはOSの授業が2つあってこれも両方取ったのだが、もう一方はOSそのものについての授業はほとんどないので、OSについて勉強したい人はこちらを取ると良い。が、普段ある程度低レイヤープログラミングをやっている人だと、まあ大体勉強したことあるねみたいな感じの内容ではある。学部時代にOSの授業を取らなかったことから来る不安のようなものが払拭できたのはよかった。

CSE6250 Big Data for Health Informatics

ビッグデータ。授業の名前にあるようにビッグデータのヘルスケアへの活用に直接興味があるわけではないが、機械学習ビッグデータについて学べる授業なので取った。微分線形代数は久しぶりに触れて、大学数学を復習するのに丸一日使うといったことがあった。 この授業を取る前は機械学習はやったことがなかったが、かなり広範な技術を一通りカバーする内容になっていて、とても良い入門になった。具体的には、課題を通してNumPy、pandas、scikit-learn、Hive、Pig、Spark、PyTorchの全てに触れるので、機械学習ビッグデータ大体やったことあるなみたいな気分になれる。グループの自由課題では人間の睡眠データから病気になる確率を予測するモデルをPySparkで作ったりした。個人的に面白いと思ったのは生徒間で機械学習のモデルの性能をKaggleコンペする課題が2回あることで、しかも順位が成績に影響するところ。公開データセットでは1位だったが、最終順位が出る非公開データセットでは一気に29位に落ちるとかあった。

CS7643 Deep Learning

ディープラーニング。この手前に取ったCSE6250でもディープラーニングに触れはするしPyTorchの使い方くらいは学べるのだが、この分野一つをとってもたくさんの要素技術があるので、ちゃんとディープラーニングに関して理解したければこの授業を取った方がいいと思われる。人気のある授業で、割と最近追加された授業なこともあり、かなり新しい論文の内容にも触れるのが良い。バックプロパゲーションの基礎、CNN、言語のモデリング、AttentionやTransformerなどについて学ぶ。 この授業にはKaggleコンペはなかったが、現場で最先端の精度を出すのに使われているモデルはこうやって動いているんだなという意識があり、楽しんで取り組めた。グループ課題では食べ物の写真からレシピを生成するモデルを作った。 レシピのデータセットを触ってると、前職クックパッドのレシピも出てきて面白かった。

CS6250 Computer Networks

コンピュータネットワーク。インターネットを支える技術を一通り触る感じ。当然ある程度知ってる話も多かったけど、一度もTCP/IPについて体系的に学んだことがないみたいな不安がなくなって良い。 BGPとかネットワーク屋さんじゃないと普段触れることはなさそうだし。 インターネットで障害が発生した時に原因についての議論がある程度理解できるようになったり、何かをダウンロードしてくる時の速度の変化について後ろでどういうアルゴリズムが動いてそうなってるのか多少想像することができるようになって楽しい。

CS6515 Intro to Graduate Algorithms

修士向けアルゴリズム入門。卒業要件を満たすために重要になるため履修登録的な意味で人気な授業。僕の場合これが実質必修だったので取ったが、アルゴリズムの問題は純粋なパズル的面白さがあるので楽しめた。 動的計画法、分割統治法、高速フーリエ変換RSA、グラフアルゴリズム、最大フロー問題、線形計画法、P vs NPなどを扱う。学士で扱うよく聞くようなアルゴリズムAtCoderで水色を取る活動をしていた時に復習していたのだが、そこでは学べなかったアルゴリズムをここである程度知れたのはよかった。 こういう知識を活用する頻度が普段そんなに頻繁に発生するわけではないが、スケーラビリティとか計算量の複雑性とかを議論する際、ある程度複雑な理論を理解した経験があると、それより少し易しい話をしている時に確かな自信に裏付けされた議論や心の余裕ができる気がする。

CS8803 Compilers - Theory and Practice

コンパイラコンパイラのフロント、ミドル、バックエンドの理論を全部触り、大学教育に使われるTigerというプログラミング言語MIPSコンパイルするコンパイラをスクラッチする課題がある。 正直独学でかなり手を動かしてきた分野なので最初からほとんど知っていたが、あんまりフロントエンドに興味がないのもあり、そこの基礎であるNFAやDFA、LLといったところの理論を抑えられたのはよかったと思う(多分自分では勉強しないから)。Ken Thompsonは正規表現をNFAに変換するアルゴリズムも発明していてすごいなあとか。

僕は過去にいくつか言語処理系を作っているが、大体はインタプリタでコード生成が不要か、LLVMとかを使ってコード生成をしているとかで、アセンブリを直接吐くコンパイラを一から最後まで書き上げた経験がなくて *7、それが今回できたのはよかった。レジスタ割付をやるとバックエンドやってる感が出て良い。TAや他の生徒とコンパイラの性能でランキングを競えるのが楽しかった。

CS6210 Advanced Operating Systems

OSの発展的内容を扱う授業。OSに関しての理解は前提知識とされる授業で、OSそのものに関する授業はほとんどない。 かわりに、OSを使ったシステムデザインや分散システムにひたすら触れるという感じの授業。 毎週3~4つくらいの独立したシステムやアルゴリズムに関する議論が行なわれるので、割と密度が高い。 システムデザインの議論が好きな人は楽しめそうな内容だが、扱われるシステムが結構古かったり、アカデミアの外では使われていないようなものだったりと、よく実用されているシステムの設計について議論する他のクラスに比べるとやや興奮度の低い内容だった。 ただ、分散システムの話題にもある程度触れ、後述する分散システムの授業で何度か言及される授業なので、取っておいたのはよかったと思う。

CS6460 Educational Technology

EdTech。技術の教育への応用という分野には興味はないのだが、これは普通に履修登録できるクラスの中で唯一、多少自由にテーマを選んで研究ぽいことができる授業なので、修士論文を書かずに卒業するかわりにここで多少研究の経験を積んでおくことにした。 学内の教授と知り合いになると、その先生に一筆書いてもらうことでCS8903というコースを取り普通に研究をして単位をもらうことも可能なのだが、特にそういう関係を築くチャンスもなかったので、気軽に取れる方を取った。

実際この授業では論文の見つけ方、論文の読み方などを教わった後、何度も論文ぽいものを書いて添削してもらう経験ができる。ただ、研究そのものの経験はできるものの、研究の成果物は何らかの方法でEdTechに紐付けないといけない。一方、任意のテーマについて教えるコンテンツを作る、といったものでも教育に関連してるとして許容されるため、例えばポーカーの戦略についてまとめるサイトを作っている人もいた。 僕は割と本当にEdTechぽいがちゃんと自分の興味もある課題をひねり出した。具体的には、画像やサイト内のテキストから知らない英単語を抜き出し、任意の辞書で意味を調べ、それを自動で単語帳アプリに登録するみたいなものを作った*8。 英語の語彙が弱いので、単語帳で勉強する労力を下げられるようなものを作れてよかった。

CS7210 Distributed Computing

分散システム。僕が取った奴の中では一番最近追加された授業で、入学時点ではこういう授業がなくてガッカリしていたのだが、取れてよかった。 社内の輪読で割と分散システムに関する論文を読んでいた経験から、これも知っているか業務の経験から理解しているものがちょくちょくあったが、分散システムの基礎的な範囲をいろいろ触っているので知らないものもまあまああり、結構勉強になった。 論理時計、一貫性、レプリケーション、 分散合意などに触れる。Amazon AuroraGoogle Spannerのような、流行りのクラウドが採用しているアーキテクチャに関する議論があるのもとても楽しい。

この授業で良いのは全ての宿題を通して分散KVSを作るところ。スケーラビリティのためにシャーディングが可能で、各シャードを扱うクラスタはPAXOSで書き込みのログをレプリすることで耐故障性を実装し、そしてそのクラスタ間で2フェーズコミットを使うことで複数シャードにまたがる分散トランザクションを実装するというもの。で、これを実装する際に分散システムを作るフレームワークのようなものを使うのだが、それを使って実装すると、その実装で発生する状態遷移の組み合わせを全て検証するテスト、つまりモデル検査(TLA+みたいな奴)のようなことが可能になっていて、あらゆるコーナーケースで分散合意と進捗を保証しないとテストが落ちるようになっていて、これが難しい。分散システムの設計力が真に試される課題で、面白かった。

おすすめ

僕のお気に入りは CS7210 Distributed Computing と CS8803 Compilers。 単に僕個人の好みの分野で選んでいるという感じもあるが、上述したような課題の実装はやったことがなくてやってみたい、という人が受けたら確実に楽しめる内容だと思う。 ちなみに OMSCentral という授業レビューサイト上では、これらはそれぞれWorkload 1位の授業とDifficulty 1位の授業なので、最難関の授業でもある。楽な授業を取るより、本気で取り組んでやっと満足な成果が出る方が面白い。

成績

GPA: 3.90 / 4.00 だった。Deep Learningがあと0.55点あれば完璧な成績表 *9 になってたのが惜しい気持ちだが、もっと余裕でボーダーを超えられる実力をつけられていなかったので仕方ない。

学期 番号 名前 Grade 点数 A要件
2020 Fall CS6291 Embedded Software Optimization A 94.96 86
2021 Spring CS6200 Graduate Intro to Operating Systems A 87.2 80
CSE6250 Big Data for Health Informatics A 96.36 90
2021 Summer CS7643 Deep Learning B 88.95 89.5
2021 Fall CS6250 Computer Networks A 90.54 90
CS6515 Intro to Graduate Algorithms A 96.12 85
CS8803 Compilers - Theory and Practice A 94.23 87
2022 Spring CS6210 Advanced Operating Systems A 93.78 89.5
CS6460 Educational Technology A 96.75 90
CS7210 Distributed Computing A 89.2 84

まとめ

比較的安い授業料でいろいろ学べて楽しい。 修士を持っている人や、博士を持っていて他の大学で教師をやっている人もここで生徒をやっていたりするので、もう学位は持ってるという人も気軽に学び直しに来れる場だと思う。

*1:この部分は元々注釈で説明していたけど、読まれていなくて誤解が発生していたので、追記で本文に変更した。

*2:例えばソフトウェアエンジニアがH1Bという就労ビザを取ろうとすると、アメリカのCS修士があると2回抽選を受けられるが、学士や日本のCS修士では1度しか受けられない。また、グリーンカードを取る際も、学士ではEB-3、修士ではEB-2、博士ではEB-1という風に使える申請カテゴリが変わり、当然より良い学位を持っている方が一般には申請が早く済む。

*3:どうも基本的に皆フルタイムで働いてるからか、この枠をフルで使い続ける人は少ないようで、多くの人は3-4年かけて卒業するらしい。このプログラムのディレクターであるDavid Joynerに見せてもらったグラフの年では、最短の5学期で卒業したのはたった1%、6学期で卒業したのは5%しかいなかった。YMMV。

*4:なので、授業は子供が寝てから自分が寝るまでの時間だけ取り組んでいた。従って平日か休日かに関わらず20-24時の1日4時間が基本という感じだった。

*5:僕は締切が近付かないとあまり生産性が出ない人間なので、同時に3つ授業を取ると締切の数が3倍になり、従って生産性も3倍になるため効率がよかった。

*6:学部の4年間ずっとプログラミングのアルバイトをしていたのだが、さっさと卒業要件を満たして業務のプログラミングに専念する学期を作って社会人に備えたいという謎の危機感があり、3年前期までにほとんどの卒業要件を満たし、3年後期は実際必修を水曜朝1つ取ったらそれ以外はバイトをするという生活を始めたのだった。で、OSの授業はたまたま3年後期に予定されている授業だったため、自分個人の予定と折り合いがつかなかったという感じ。

*7:学部の授業で、先生が用意したx86アセンブリを吐く実装を少し拡張するみたいな課題はやった

*8:個人開発を黒字にする技術 https://k0kubun.hatenablog.com/entry/surplus で話していた奴はこれのこと

*9:点数は残らず、公式な記録はletter gradeしか残らないため

個人開発を黒字にする技術

最近は個人開発は自分のOSSのメンテで手がいっぱいになってしまったのでサービス開発のようなものは普段あまりやらないのだが、大学院*1で今学期、何作ってもよいという感じの授業を取ってWeb/iOS/Androidアプリ*2を全て作るという体験をする中で、たまたま個人開発のコストを抑える活動をしたので、その時に調べたり考えたりしたことを書いておく。

Herokuで無料にする

Herokuでは毎月550時間free dynoが使え、クレジットカードを登録しておくと更に450時間、合計1000時間無料で使える。Herokuは30分アクセスがないと一旦停止するが、今回授業で作ったサービスでこれを使い切らないことは明らかだったので最初はこれでセットアップした。セットアップも簡単だし、PostgreSQLも無料でついてくる。

ただ、コールドスタートに10秒くらいかかり、これがこのサービスではUX的に致命的だったため、元々運用していたVPSに同居させることで高速化を図った。

安いVPSの選定

個人VPSは10年くらい持っていて、これまで様々なVPSサービスを試してきたが、今回いろいろ整理する前はConoHaを使っていた。最初はDBサーバーとVPS 1台で2484円という感じだったが、安くするためにDBをVPS同居にして1848円までは圧縮した。

ただ、今回もう一つサービスを足すにあたって、当時のVPSではもう一つWebサーバーを立てるほどキャパシティに余裕がなく、かといって家計を削って値段を上げるのもなあという気持ちもあった。そもそも、USに移住したので日本のVPSだとレイテンシにやや不満があった。

そこで、安くてリソースが多く、可能なら自分に近いリージョンのVPSを真面目に調べ直した。結論を書くと、個人開発のコストはDB次第という記事のブコメにも書いた vCPU 4コア / 8GB RAM / 100GB NVMe *3 で月 $8.24 のVPSを発見し、それを使っている。ContaboのCloud VPS SのUnited States (Central)がその値段で、EUだと月 $6.99、Asiaだと月 $9.99 になる。

他にもいくつか有望ぽい奴は見つけたが、VPSCOMPというサイトで見つけたものが多かった気がするので、とりあえずこのサイトで好みのやつを探していただくのが良いかもしれない。

サーバーメンテの労力を最小化する

Kubernetesをやめる

4年前に練習用途で個人サーバーをKubernetes化したのだが、ある日突然クラスタがクラッシュして再起不能になったこともあったりと管理コストが無ではないし、Kubernetesそのものがめちゃくちゃリソースを使うのでサーバー代はかさむし、会社で自分のチームがEKSを使い始めて触りたければ触れる状態になったので個人サーバーではやめることにした。今はものすごく素朴に動かしているので、突然何かがクラッシュするみたいな状況は見ないし、したとしてもsystemdがサービスを再起動して勝手に直ると思われる。

式年遷宮を自動化する

自作プロビジョニングツールであるmitamaeを使って個人サーバのセットアップを自動化しており、これは何年も秘伝のタレ的に使い続けられている。Ubuntuのバージョンを上げる時にdist-upgradeで済ませたこともあるが、サーバーを立て直す労力がそこまで高くないので、VPSごと立て直してしまう*4ことが割とある。これでついでにDBサーバーのバージョンも上がりDBメンテ相当になるが、個人サーバーなので多少のダウンタイムは許容できるし pg_dump してrestoreしてくるけど、9GBほどのDBではすぐ終わる。そんな頻繁に必要なわけじゃないし、例の記事がいうほどDBサーバーのメンテナンスは大変ではない気がしている。

Let's Encryptの自動化

Let's Encryptの証明書が3か月おきに失効するので、これの更新がうまくいっていないのを誰かに指摘されるということが多く、プロビジョニングが自動化された環境下ではこれが一番運用労力がかかっていた印象がある。普通はcertbotを使えばいいと思うのだが、何か割とセットアップに手こずった記憶があり、Ruby製のacmesmithを使っていて、自分の得意な言語かつ読みやすいサイズなので何かうまく動かなくてもコードを読むことでどうにかしやすくなった。ここ最近は壊れることがなくメンテナンスフリー。

Google AdSenseの設置

サイトに広告を一切貼っていなかったころ、VPSの運用負荷を下げすぎてほとんど触ることがなくなり、しかもそこで動かしているアプリもそんなに触る動機がない状態になり、金の無駄なのでVPSを止めるか検討したことがあった。ただ、多少アクセスのあるサイトを動かしていたため、止める前に試しに広告を貼ってみたところ、ConoHaのVPS代より売上がコンスタントに出る感じだったので、そうすることにした。

Gitstar Ranking *5 という、GitHubのスターの合計数でランキングを出すという非常に浅ましいサービスを8年前に作ったのだが、1日1000~2000PVくらいしかアクセスがないのに毎月$20-30くらい売り上げている。画面全体に出る広告は使っておらず、自分のPCの画面サイズではトップページでファーストビューに入ってこない程度に控えめにしか貼っていないのだが、それでもクリックしてくれる人がいるらしい。

モバイルアプリの公開費用

授業の成果物のため、React Nativeを使ってiOS / Androidアプリを作ろうとしたところ、作ろうとしているものの要件上やや厳しい感じになり、そこがFlutterでは問題なさそうな感じなので、今回Flutterを使って簡単なモバイルアプリを作った。

DartとFlutterに関する感想はこの記事ではおいておくが、他の生徒にアプリをテスト公開するにあたり必要になったコストの話を書く。金はかかったが、元々動かしていたサーバーから発生している利益の中には収まってそう。

Firebase

今回作ったアプリではGoogleアカウント認証を使っていて、これは本来Web Viewを使うと別にFirebaseとか使わなくても実装できるのだが、それを実装しているサードパーティのFlutterプラグインが壊れており、公式が提供しているFlutterプラグインを使ったところ、流石Google、これは裏側にFirebaseが使われており、途中から有料になるサービスをまんまと使い始めさせられてしまった。ユーザー100人までは無料で、それに到達しなさそうなのでそのままやっているが、まあいざとなったらFirebaseを気合で外せばよさそう。

Google Play Developer Program

Androidアプリの評価に関してはapkを配布するというのでもよかったのだが、他の生徒がアプリの評価に参加する障壁を下げるため、Google Playが公式に提供しているTesting機能を使うことにした。これは $25 払ってGoogle Play Developer Programに入らないと使えないが、1回払ったらそれで終わりだし、額的にもAppleのそれに比べたらとても良心的だと思う。なおProductionのレビューも通したので今は普通に公開リリースして使っている。

Apple Developer Program

iOSアプリの開発でお賃金をもらうのをやめてから9年くらい経つが、少なくともTestFlightにアプリを公開しないとiOSユーザーの生徒にテストしてもらえないため、9年ぶりに再加入した。これはもう更新しないつもりで使っているが、年 $99 というのは高いなあと思う。今はPixelユーザーで次はiPhoneにしようか検討しているのだが、自分でアプリを作って使いたくなった時に年 $99 払わされるのは厳しいのでうーむという気持ちになっている。

確定申告

USに住んでるのでありとあらゆるものを確定申告しているのだが、この辺のコストをAdSenseの売上の経費として申請すると節税で更にコストが抑えられる。

まとめ

特にマネタイズに気持ちがなくて大して使われてないサービスでも、ほぼ無の運用労力と控えめな広告だけで黒字にでき、それで残りのサービスは自由にやることができる。

*1:今週期末試験が終わって、点数はまだ確定してないけど、明日卒業式。家庭の事情により出席しないけど

*2:厳密にはそれと連携するChrome拡張も作って公開している

*3:本来50GB NVMeか200GB SSDの2択なのだが、契約した当時はその時契約すれば同じ値段でNVMeが2倍の容量使い続けられるというキャンペーンがやっていた

*4:これを式年遷宮と呼んでいる

*5:元はGitHub Rankingという名前だったのだが、GitHubに怒られたので変えた