2020年にやったこと

ハイライト

  • 子供が産まれた
  • 大学院生になった
  • Ruby 3x3 を達成した

全てが妻の大きな助けがなければ有り得なかった。すごく感謝している。

発表

子供ができる前に発表か録画ができないものは基本的に応募もしなかったし誘われても断わっていた *1 ので例年より数が少ない。幸運にもそれ以前にお声がけいただいたところで登壇させていただいた。

毎回新ネタをいれてるつもりではあるものの、ここ数年ほとんどRubyJITの話しかしていない…。ちなみにRubyConf Chinaは初のKeynote枠でのお誘いだった。コロナな分スピーカー集めるの大変そうだったのと、オンラインなのであまり違いを感じなかったというのはあったけど。

仕事

去年書いたサービスの切り出しが一区切りついて、それを活用して新プロジェクトが1つ以上効率的に進められていた感じがするのでよかった。切り出しの完全な終了が終わらないと各所に負担がかかるもののプライオリティが下げられているというのが残念ポイント。

育休後の後半は他の人が二人でやっていたその新プロジェクトに数名と僕が加わりつつチーム内でのリードを僕がやっていた。入社してからいつも一人でいろんなチームのリポジトリに自分でコードを書いて解決しにいくということが多かったが、そういうムーヴをしているとどんなにいい仕事をしても評価されにくく、実際会社へのインパクトがスケールしないのも事実なので、重要なものに集中しつつ協調作業もしやすいようにうまくマイルストーンを切ったり、自分が得意なタスクを自分が消化し続けるのではなく他の人もできるようにするのを意識して働くように変わった。

US生活

コロナなのでかなり長い間ロックダウンされていた。普通に店内での外食や映画館やゲーセンがやってるらしい日本はすごい。家族と過ごす時間や趣味の開発以外の唯一の楽しみであるタピオカドリンクをほぼ毎日飲んでいる。あとは大体だっこ紐で散歩。

コロナの影響でトランプがビザでの入国を困難にした関係で、現時点では一応可能ではあるものの再入国のリスクがかなり高くなってしまったので、僕は今年は日本に一秒もいなかった。ベイエリアには治安が最悪のところにしか音ゲーが置いてあるゲーセンがないので、毎シリーズSP八段だけはとりあえず受け直している音ゲーもやっていない。

生活の基盤整備が落ち着いた夏ごろからUSでの資産運用をやり始めた。いまだに資産の大部分は日本円でそっちはもう動かせないんだけど、USDの運用だけで毎月平均10万円相当の利益がでており、そのままのペースで老後まで行って欲しい。

あと、会社のご厚意で渡米後すぐ始めていたグリーンカード申請の準備が終わり、やっと今月申請が始められた。EB-3なんだけど、運が良ければここから1年半くらいで終わりそうだが、コロナな上にS.386が通りそうなので取得までここから2年、最悪3年くらいは普通に覚悟している。

勉強

大学院入学に必要だったTOEFL 100点が本当に大変だった。口頭で頻繁に英語を話すチームに入ってからもう3年弱経つが、いつまで経っても英語わからんなあという気持ち。実用上はリスニングが一番苦手で、スピーキングはどちらかというと時間を投資できているつもりなのだが、試験を受けるとリスニングの点数が高くてスピーキングが低い。

TOEFL試験勉強の間にリーディング速度の向上が感じられ *2、英文ライティングの型みたいなのを覚えて書く構成に自信が持てるようになったのはよかった。

入学後も楽しくやっている。大体前回の記事に書いてその後は冬休みなので今はそれ以上書くことはない。

ブログ

アメリカ関係のブログを4つはてなブログに書き、Ruby 3の話をMediumに、ほぼ自分向けの技術メモは8個Qiitaに書いた。

OSS活動

新作はrspec-openapiで、こういう一瞬で作れるけど爆裂に便利な小さいツールは思いついたら書くのをやり続けたい。JIT開発に必要だったのでdwarfを勉強してdwarftreeというのも書いていて、これはMJITの開発をする上で便利に使っている。

とはいえいろいろ作り続けた反動で、多い時は一日3回、少なくとも週に数回はGitHubのissueかPRの通知が来るようになり、ほとんど真面目に対応しているんだけど時間の配分が結構難しくなってきた。自分がやりたくてやっているJITの開発はさておき、それと育児や学業の他に別に時間が余ってるわけでもないのに他人の要望に対応するというのは正直大変*3になってきたのだけど、GitHub Sponsorsで毎年Ruby Prize最終ノミネートくらいのお金がいただけるようになったので、実はこれで結構精神的に救われている。

メインにやっているRubyJIT開発は、2020年の目標にもしていたRailsの高速化は大きな進捗はしたものの達成できず、その分最も公式なベンチマークであるOptcarrotの3倍高速化を期末試験が終わったあたりから本気を出すことでどうにか達成した。Ruby 3x3以外にもかなりいろいろやっていて、妻の多大な協力のおかげで、一人が一年で作れる範囲ではとても多くの成果を出せたと思う。

2021年は

まずコロナが収束して欲しいという切実な思いがある。長らく会えてない人に会ったり、子供にいろんなことを体験させたりしたい。あと帰国の自由度が上がるよう、グリーンカードの申請が終わらないまでも進捗はして欲しい。

個人目標は、2017年から言ってるけどJITRailsが速くなるようにするのと、取る授業全部成績A、といったところ。

*1:なのでRubyKaigiもCFP通ってたけどTakeoutには登壇しなかった

*2:というかTOEICでもそうなんだけど、リーディングがめちゃくちゃ遅くて解ききらないことが多かった

*3:労力をかけずにマージできるPRが来ることは1%くらいしかなくて、他は1回あたり数分から数時間飛ぶ

リモートでアメリカの大学院に通い始めた

今年春に出願、夏に合格して秋学期からオンラインのコンピュータサイエンス修士コースで勉強している。ちょうど秋学期が終わって成績が返ってきたので、どういう感じだったか書いておく。

どうして進学したのか

僕は学士で卒業するときどちらかというと大学院に進学をしたかったのだけど、当時お金があまりなかった*1ので、学費と東京での生活費を稼ぐためには単位が取り終わったころに一日8時間週3〜5回やっていたアルバイトを続ける必要があり、そんなに働いてたら勉強もろくにできないだろうなと思って進学しなかった*2

のだが、@rui314 さんが社会人のまま受けていたスタンフォードのコンピュータサイエンスの授業の話を読んで興味を持ち、実際同じコースで授業を受けてみたところ、面白いし働きながらでもいけるな*3という気持ちになった*4ので、進学することにした。

なぜリモートなのか

冒頭のツイートに書いてあるが、コロナだからではなく、社会人を続けながら授業を受けるためだ。オンラインで受講することにも当然ながらデメリットはあるし普通に社会人をやめて修士に行く人もいる*5のだが、コンピュータサイエンスだと一人でもくもくとプログラミングをしている時間が大切だと思っていてそこの体験は変わらないし、まあそもそも家族を養う必要があるとか、仮にそうじゃなくても社会人歴を伸ばし続けた方が短期的にはお得そう*6だなという感覚があった。

出願手続き

今年の春以下の2校に出願し、どちらにも合格した。

  • Georgia Tech: Georgia Institute of Technology
  • UIUC: University of Illinois Urbana-Champaign

U.S. News - Best Computer Sicence Schoolsではどちらも上位につけていて、世界大学ランキングで38位と48位*7なので結構いいところに合格させてもらえたなと思っている*8

どちらもオンラインのコースがあり、普通の学生と同じ学位が取れる。受けられる授業の内容*9を見比べて、Georgia Techの方が面白そうだなと思っていたのでそちらに決めた。低レイヤーや分散システムに関する授業を主に受け、残りの単位で機械学習ディープラーニングをやろうかなあという気持ちでいる。Georgia Techには、機械学習で自動投資プログラム書く授業や、Unityでゲームを作る授業など、いろいろある。

GPA

Georgia TechはGPA 3.0、UIUCはGPA 3.2を原則*10要求している。前授業受けてたスタンフォード行かないの? とは数回言われたし実際行きたい気持ちはあった*11のだが、スタンフォードではGPA 3.5が要求されており、そこに届いていなかった*12

私の出身の東工大では成績表にGPAが出ない*13ので、WESというところに成績表を送ったところGPA 3.36と計算された。在学当時は将来良い成績が必要になるとは思っておらず、文系科目で単位ギリギリの60点(GPA的には0)を取ったりしていたので、まあしょうがないかなという感じ。

TOEFL

Georgia Techは100点、UIUCはオンラインでは103点がTOEFL iBT(120点満点)の足切りになっている。両校ともGREを要求しないのでテストらしいものはこれしかない。ので、これの準備がダントツで大変で、問題集を9冊こなし、一回2万円する試験を8回も受け、102点*14を取るまでに半年以上かかった。

TOEFLの何が大変かというとまず静かにテストが受けられる試験会場の予約バトルが大変*15で、しかも採点対象に含まれない問題が挿入されランダムに問題数が変わり何問になるかで解きやすさが変わるし、そして僕の実力で合計100点取るには、全部一発勝負のスピーキングは一つミスると受験し直しみたいな感覚だった。

推薦状

どの学校も3つ推薦状が必要で、最低1つはアカデミアの人からもらう必要があり、主にその推薦文が重視される。学部の時に所属していた研究室の渡部先生からとてもありがたい内容の推薦文をいただけたため、この点に関しては安心することができた。残り2つは同僚の上司と元上司からいただいた。

Statement of Purpose

エッセイ。何が目的で入学し、何故大学でやっていけそうかを書く。普段やってるJITコンパイラの開発や仕事の分散システム開発をする上で役に立ちそうだし、実際に修士の授業受けたらAだったからいけるのでは、みたいなことを書いた*16

授業はどうだったか

OMSCS

Georgia TechのOnline Master Computer Scienceコースのことを略してOMSCSという。僕の知っている範囲でも同僚の@Lewuatheさん、Railsコミッターの@schneems、他にも@takpさんや@_rdtrさんが参加しているのを見て雰囲気は知っていた。日本に住んでても普通に受けられる。

スタンフォードのSCPDは実際に通学している生徒が受ける講義の録画を見るのだが、OMSCSではあらかじめ作られた講義動画、それもオンラインはキャンパスが違う扱いでオンライン用に作られたものが基本的には使われ続け、たまにアップデートされたりされなかったりするらしい感じになっている。

これは善し悪しで、普通に通う生徒と同じ授業をリアルタイムに受けたくても受けられないのは残念だが、スタンフォードの講義動画を眺めてると近い生徒と相談してみてくれみたいな感じの時間が数分続きオンラインの生徒は置き去りになったりするのに対し、OMSCSだと最初からオンライン用に作られたクイズが途中で出てきて自分のペースで解いたりといったことができる。オンライン受講に最適化された体験という感じである。

試験監督

以前の記事で書いた通り、スタンフォードのSCPDでは現地で受験できない場合は職場の上司などに対面で試験監督を依頼する必要があり、これが面倒だった。まあ当時と違いベイエリア在住になった (むしろGeorgia Techには飛行機じゃないと行けない) ので別にこれは気にする必要はなくなるはずだったが、コロナ中のShelter in Placeで対面試験監督が無理だった間どうなったのか気になる。

ここに関しては、OMSCS生の同僚が一人で試験の様子を録画して提出する感じなので楽と言っていたのを事前に聞いて安心していた。僕が受けた授業ではHonorlockというのが使われていて、パソコンの画面全体と自分の様子を一人で録画し、画面や顔や音の変化を察知して怪しそうな場面が検知される感じになっていた。これ生徒の間では不評っぽいけど、上司の業務時間を毎セメスター消費するよりはよっぽど精神的に楽だと思う。

CS 6291: Embedded Systems Optimization

タイトルの通り組み込みシステム向けの最適化について。僕は組み込みシステムにはあまり興味がないのだけど、OMSCSのコンパイラの授業を持っている先生がこの授業をやっていて、かつこの授業では組込みシステム向けのコンパイラは題材としつつも、レジスタ割り付けや命令スケジューリングといったコンパイラバックエンドに関する内容がメインとの評判で、日々RubyJITコンパイラを実装している関係でそこに興味があったので受けることにした*17

先生が書いたコンパイラ最適化に関する論文やドラゴンブックが教科書として使われ、課題で提供されたIRに対しレジスタ割り当てを行なうアルゴリズムPythonで一から実装したり、組み込みシステム向けの命令スケジューラ*18C++で書いたりする。講義で出てくるコンパイラ最適化問題は大体がNP完全なのでヒューリスティックを使う必要があるのだが、普段コンパイラのインライン化判定を実装する時にも使うような考え方なので大変参考になる。あと、コードを最適化するときにレジスタ割り当ての気持ちをなんとなく考えることができるようになる。

宿題とプロジェクトと期末試験がほぼ均等に考慮されて成績がつけられ、85点以上だとAになるぽい。僕はトータルで95点でのAだった。

これから

学部の時のGPAに対して割と残念な体験をしたので、(今のところそういう予定はないけど) 将来Ph.D.に進学したくなった時とかのことを考え、GPA 3.8~4.0あたりでの卒業を目指している。次のセメスターではHadoopやSparkを使ってBig Dataする授業を受けようと思っている。

*1:別に苦学生というほど貧乏でもなかったが、授業料半額免除が通るくらいの水準。

*2:この辺の気持ちは当時も https://k0kubun.hatenablog.com/entry/2015/02/19/012927 に書いた

*3:当時と何が違うかというと、大学も仕事も日中に行かないといけないという状態ならやはり大変だと思うが、大学の授業の受講が夜だけでできるというのが大きかった。

*4:そういう気持ちだっただけで、実際には夏に子供が生まれたので、今年はあまりいけるなという感じではなかった。

*5:katryoさん https://katryo.hatenablog.com/entry/2017/12/22/131447 やserihiroさん https://serihiro.hatenablog.com/entry/2019/12/07/210355 など

*6:当たり前だが大学院にかかる年数人間がフルタイムで働くとめっちゃ金がもらえる。それから、例えばジョブタイトルの説明には経験年数の目安が書いてあったりとか、最終学歴が学士でも社会人歴が長いのでグリーンカードの申請がEB-3ではなくEB-2になった人を見たりした。

*7:東大は36位、京大は65位という感じ

*8:ちなみにGeorgia Techはコースごとに出願者数と合格者数を公開しているのだけど、通常のコースに比べオンラインのコースは合格者数と合格率が共に圧倒的に高い。単純に学生の数をスケールしやすい仕組みだから枠が増やせるという話だと思うが、枠の制限が緩い以上は合格のハードルは少し低いと思う。

*9:ふつうコンパイラ書く授業では低レイヤーの言語が使われやすい気がするけど、UIUCのコンパイラの授業ではHaskellが使われる https://pages.github-dev.cs.illinois.edu/cs421-fa20/web/ というような個性があったりする

*10:多少低い程度なら他の要素でカバーできることもあるらしい

*11:僕が最初に面白そうと思った授業もそこだし、以前スタンフォード卒の同僚から、シリコンバレーでは履歴書にスタンフォードとあるとその話で盛り上がったりする、みたいなことを聞いたりもした

*12:まあそれは最初から察していたけど、実際内部でいい成績を取ってそこの先生からの推薦を貰えれば受かりそうだなと当時は考えていた。一方でそもそもGPAで足切りされるかもわからないのに最大70万円かかる授業をそれを目的に何個も取るのは正直辛いし、いくら点数が良くても先生に記憶してもらうまでにはかなりハードルがあることもわかった。あとTOEFLの対策だけでも半年以上かかっていたのに、受けた2校では不要だったGREの試験対策をするのも大変だなあと思っていた。

*13:在学当時試行GPAというやつはあったのだが、ふつう4.0スケールのはずが最大GPA 5.0になる感じだった記憶がある。どの道正式な成績表には出てこないので意味はない。

*14:UIUCに実は1点足りていない。が、第一志望はGeorgia Techだったのと、どの道もう一回受ける余裕がないところまで締切が迫っていたので諦めた。まあなんか他の要素でカバーされたのかもしれない。

*15:takutiさんの記事が参考になる http://takuti.hatenablog.com/entry/2014/10/29/121513

*16:ちなみに過去に受講したことがある大学全ての成績証明書が要求されるので、スタンフォードでの成績証明書も提出していた

*17:あと、ラズパイ上でArmの命令エンコーディングを最適化してベンチを取るみたいな課題があって、始まったころまだ論理Arm社員だった https://blog.treasuredata.com/blog/2020/07/07/arm-proposes-to-transfer-ownership-of-treasure-data-to-softbank-group/ のもあり、なんとなく自分の中で今が旬な授業みたいな感もあった

*18:これは組み込みシステムの面白いポイントだと思うのだけど、エネルギー消費を抑えるためになるべくコンパイル時に計算を済ませたいという事情があり、組み込みシステム向けの命令セットではどのサイクルでどの命令を並列実行するかを正確に指定できたりする。そのため、どのリソースはどういうレイテンシがあるかを考慮しつつ、コンパイル時に命令のスケジューリングをやるなど、コンパイラでできる最適化の幅が広く、面白い。

USの資産運用とクレジットスコア

前回ベイエリアでの収入や支出についてまとめたが、今回はUS生活でのお金に関するそれ以外の話、具体的には銀行、クレカ、投資、年金などについてこれまで調べたり考えたりしたことを書いておく。

日本に住んでる人でも、金利が0.01%や0.001%の普通預金をメインで使っていたり*1、クレカのポイント還元率が1%だったり、確定拠出年金をやってなかったりする人にはその辺りを見直すきっかけになる話もあるかもしれない。

方針

資産運用が趣味でも仕事でもなく、何もしなくても金がいっぱい増える仕組みが欲しい人を念頭に置いている。普段ほぼ運用に手間をかけずに生活し、1年に1度くらいなら運用に手間をかけてもいいが、それ以外の時間はプライベートや自己投資*2に費したい場合のお金の最適化について書いている。

銀行

Checking

現金の出し入れに使う口座。Savingsの方が一般に金利が高いので、ここには普段ほとんどお金を残さずに過ごすことになる。そのため、支店やATMの多さ (Wells Fargo, Chase, Bank of Americaが多い) や、クレカと同じアプリで管理できるといった利便性を重視してもここはあまり損はしないと思う。金利が高いChecking口座の中で自分の状況では便利そうなものがあるなら、それに変えるとよさそう。

僕は移住の最初Bank of Americaを使っていたのが、今は後述の理由によりChaseを使っているが、Sign upボーナスの維持に必要な半年が経過したらChase以外に変えるかもしれない。

Savings

貯蓄に使う口座。金利がCheckingより高くてもインフレ率より低ければここに資産を置いておくと価値はどんどん下がっていくのだが、何らかの理由により現金を取っておく用事がある場合はなるべくここにいれておくと比較的まともな金利で保管できる。定期預金とは違い、引き出したければいつでも気軽にtransferできる。

僕が日本にいたころ、アメリカの銀行口座は金利が2%とかでお得なんですよと聞いたことがあった。実際僕が使っているAmexのSavingsも2年前は金利2.1%だったらしいのだが、コロナの間にどんどん下がって今は0.6%になった。世知辛い。他のSavingsでも大体そんな感じ。

クレジットカード

クレジットスコアの維持

以前、クレカの申請にはクレジットヒストリーが必要で、クレヒスにはクレカが必要であるというブートストラップ問題について書いたが、単にブートストラップした程度のクレジットスコアでは欲しいクレジットカードが手に入らないことがある。

移住したころ、クレジットスコアを上げるために車のローンを契約したりしていた*3ため1年経たずにクレジットスコアが750弱 *4 に到達したのだが、その後1か月で90ptsスコアを落としてしまったことがあった。

これはクレカ費用の支払い方法が原因だった。というのも、Auto Payは設定していた *5 のだけど、Due Dateに支払うように設定していて、クレジットヒストリーにレポートされるタイミングはその2日前のStatement Dateだったので、かなり枠を使ってる状態でレポートされてしまったのである。これに気付いてからはStatement Dateの1日以上前に、DueではなくBalance全部を払うといったAuto Payにしている。その結果720弱まですぐ戻ったのだが、それ以上はほとんど戻らなくなってしまった。注意されたい。

Chaseのクレカの申請

Chaseのカードを申請する場合、過去24か月の間に銀行を問わず5枚までしかクレカを開設させないという、有名な5/24 Ruleに気をつけなければならない*6。Chaseが発行するカードに今後欲しいものがあれば、他のカードより先に作るのを検討する必要がある。

Chaseは就労ビザで発行されたSSNを持つ人のクレカ申請を受理しなくなったというが流れた時、Chase Freedom Unlimitedというカードを申し込んでみたのだが、当時750弱のクレジットスコアにも関わらず落ちた。

数日後、封書でリジェクト理由を知ったのだが、これはその噂のせいではなく、既存のクレジットの期間が短く、Chaseとの関係も浅い(無)ためであると説明があった。後者を満たすためにChaseのChecking口座を開設してそちらに全てのChecking利用を移した後、後日Chaseの支店に相談に行ったところ、クレカの期間は1年になるくらいは必要で、前回の申請から期間を開けるのとCheckingの履歴を構築するために2〜3か月待つように言われ、実際そのくらい待ったら (別だが、同程度の審査基準の) Chaseカードの審査が通った*7

キャッシュバックの最適化

前置きが長くなったが、USでの買い物で損をしないために重要なのはクレカのキャッシュバック率である。USではほとんどの店でクレカが使えるけど、これはつまりその店がクレジットカード会社に手数料を払っているということになり、自分がクレカで支払いをするかどうかに関わらずそれが品物の価格に折り込まれている。これを取り返すにはクレカのキャッシュバックを使うしかなく、その率が低いほど買い物をする度に損をしていく。

一般に、ほとんどのカードで1%は戻ってくる。消費者が全員得をするように作られているとは考えにくいので、まず1%は避けた方が良い。何に使っても1.5%戻ってくるカードはそこそこあるが、2%戻ってくるカードも普通にあるので、後者にしておくのが無難 *8。 @yusk_ さんが良いクレカをまとめてくださっており、参考になる。

特定の用途で3~5%程度のキャッシュバックが適用されるカードもあり、面倒でなければそれを使っておくと良い。例えば、僕はAmazon Prime Rewards Visa Signatureカードを持っていて、これをAmazonに設定しておくだけでAmazonでの買い物がPrime会員なら5%、そうでないなら3%キャッシュバックになる。 四半期ごとに高いキャッシュバック率を特定のカテゴリに指定してくるカードもあるけど、何が今キャッシュバックされるかを定期的に暗記し直す必要があり、方針に書いた通り面倒な運用はしたくないので使っていない*9

僕は今のところ年会費が無料のカードだけを使っている*10。これは、キャッシュバックで元を取るためには結構な額、少なくとも僕は普段使わない額を使う必要があるが、そもそもクレカは 使わなければ100%キャッシュバック なので、そもそも キャッシュバック率は高い方が良いがキャッシュバック額は低い方が金が残る という考えに基いている。

投資口座

何故投資するのか

銀行金利よりインフレ率が高ければ、銀行預金の資産価値は減り続けるという話をした。なるべく高い金利のSavingsにいれておいて耐えるという選択肢もなくはない中で、何故それよりも資産が減るリスクを取ってまで投資をするのか?

僕は少なくとも老後働かなくてもお金がなくならない状態、あわよくば働かなくてもお金が減らない状態になりたいと思っていて、そのための投資がうっかり悪い方に転んでも後悔しない程度には期待値は高くできそうで、リスクも自分が期待する程度に調整できると判断したのでやっている。

例えば2000年に40歳だった人が$300,000の (今の価値で3116万円) 貯金があったとして、USの株式市場は20年後には拡大しているだろうと期待しこれをUS株式市場全体のインデックスであるVTSAXにいれて60歳になる2020年まで持っていると、何もしなくても$1,217,397 (1億2644万円) に増え億万長者になるのである。これは何故かというと、このインデックスの全期間での平均利回りは7%なのだが、仮に20年間毎年7%増えていた場合といういい加減な計算をすると、$300,000 × 1.07 ^ 20 = $1,160,905 という感じになり、指数関数になっているから年数が長いほど複利で爆発的に増えるのである。そして、これだけ資産があると、次の年に平均の7%増えると800万円以上になるので、リタイアしてもいい感じがする。*11

最も、これが次の20年で再現できる保証は全くないのだが、決まった時間に引き出さなければならないといった制約がない場合、不況が来ても市場が回復するのを数年待ったり、あるいは老後に近付くにつれてリスク資産の割合を減らすといった対応が可能になる。

何に投資するか

株に投資することにしたとする。世の中には自分の拠出額の数十%を会社が追加で拠出してくれたりする持株会というものがあり、そんなに追加でお金もらえるならその分も含めて負けることはないだろうと枠いっぱいに投資を続け、僕の資産の99.6%が自社株だったことがある。4年後には株価は買い始めた頃の10分の1にまで落ち込んでおり、会社の追加拠出では抑えられない状態になっていた*12。個別株にはそういうリスクがある。*13

じゃあどうするのかというと、時価総額加重平均を採用したインデックスファンドを使うことで、特定の会社が暴落した時のリスクは抑えながら、市場全体が成長し続ける限りは市場の平均の儲けを得ることを目指す*14。長期的に見て市場全体が成長しなかった場合儲からないことになるが、少なくとも上記で言及したUS市場はリーマンショックからは持ち直したし、コロナで下がった時も割と短期間で回復した。この先も不況から立ち直る保証はないが、US市場が十年とかの期間縮小し続けたらかなり多くの投資家が同時に損をするはずで、それで損をしてもしょうがないと思ってもいいくらいの世界の終わり的状況だと思う。

とはいえ、世界中の投資家が世界の終わりを迎えている時、特に老後は自分の家族には世界の終わりを迎えて欲しくないので、年齢が上がるにつれ資産をよりリスクが小さい資産に移していくことが必要になる。僕はインデックスファンドだけを使ったThree-fund portfolio *15 というのを組むことに決めたのだけど、これは例えば自分の年齢と同じ%分Bondを保有するといったリスク調整が可能で、そのように年一回リバランスし続けると、老後には不況が来ても資産があまり減らないが、Bondにより、現金で持っているよりは高い利回りが期待できるという状態になる。

どのように投資するか

インデックスをベースに投資したいだけならIndex FundでもETFでもどちらでもいいことになるのだが、僕が使っている口座ではETFだと自動積立ができず冒頭の方針に反するので、Index Fundを使っている。ただし、Index Fundが何%手数料を取ってくるというのは銀行によってまちまちで、なるべく手数料が低い銀行で口座を開設しないと損をする *16 。Vanguardは手数料が安いことで有名で、僕の知る限りではCharles Schwabとかでも同じインデックスで同じ手数料のファンドがあったりする。

401k / IRA

日本でいう企業型確定拠出年金 / 個人型確定拠出年金 (iDeCo) の話。

401kが会社にサポートされているか

弊社Treasure Dataでは福利厚生として401kが提供されていているのだが、このTwitterスレを見ると401kを提供していない会社は結構ある模様。それから、次に伸べるマッチング拠出の割合や、後述のBackdoor Conversionが使えるかどうかも会社によってまちまちらしい。皆Treasure Dataに転職すると良いと思う。

401k マッチング拠出 を使い切る

401kにPre-tax contribution (Elective Deferral) をすると、収入のN%を上限に会社が同じ額拠出してくれる、という制度。401kというのは老後になる前でも10%のペナルティを課税されつつも引き出すことができるので、このN%分拠出していない人はどう考えても損をしていることになる。会社が提供しているならば、ここまでは最低使うのが基本。

401k Pre-tax contribution を使い切る

2020年は年間 $19,500 まで Pre-tax か Roth で401kに拠出できるのだけど、これがマッチング拠出枠より大きくても、残りの枠もPre-taxで使い切った方がお得。所得税を回避して拠出できるので普通の口座で投資するより得なのは当たり前としても、ある一定の課税前収入をPre-taxで拠出した場合を、After-taxで少なくなった拠出からの後述のRoth conversionで同じ利回りで運用した場合と比較すると、最終的に引き出される額が前者の方が多くなるため。

401k After-tax contribution を使い切る

After-taxで拠出するということは普通の口座で投資するのとあまり変わらずこれだけでは得ではないのだが、これをRoth 401kやRoth IRAにconvert (Backdoor Roth IRA Conversionという) するのを会社がサポートしている場合、キャピタルゲインを非課税にすることができる。Pre-taxとAfter-taxは合計 $57,000 拠出できるので、 $19,500 とマッチング拠出分を引いた残りは全てAfter-taxにすると良い。Conversionにlimitはないので、全額Rothにconvertする。

Traditional IRA を使い切る

Roth IRAというのは年収が一定以上だと拠出できず、Traditional IRAもPre-taxでは年収が一定以上だと拠出できないのだが、After-taxならば年収上限なく、年間 $6,000 までTraditional IRAに拠出することができる。そしてこれを上限なくRoth IRAにconvertすることが可能で、あなたの会社が401kを提供してなくても、キャピタルゲインに課税されない魔法の投資口座を作ることが可能になっている。結婚していれば夫婦一人ずつ口座が開くことで拠出上限を二倍にできる。

老後日本にいても引き出せるのか

まとめ

銀行の利率やクレカのキャッシュバック率のチューニングは損をすることはないので、面倒じゃない範囲でやっておくと良い。投資にはリスクがあるが、もともと老後まで引き出さないつもりなら年金に突っ込むことで所得税を無視して拠出したり、キャピタルゲイン非課税といった節税の余地はある。

*1:例えば楽天銀行は、証券口座を開設して連携しておくだけで、それを使わなくとも普通預金金利が0.1%になる

*2:特に若いうちは資産の運用に無限の時間を使うよりは自己投資にお金を使った方が経済効率も良いと考えている。一方、資産運用は複利で効いてくるので、全く考えてないのもかなり損だと思う。

*3:これはやらなくても移住後1年クレカ使い続けたら720くらい行くんじゃないかという気もしているが、自分は試せないのでわからない。近日、クレヒスが必要な用事を全部消化できそうなので、スコアの暴落覚悟でローンは繰り上げ返済しようと思っている。

*4:スコアだけ見れば多くのカードにqualifyする、そこそこ良いスコア。でも後述の通り、スコアだけで欲しいクレカが手に入るとは限らない

*5:前提として、日本と違ってクレカを作った時点では費用が自動引き落しにならない https://twitter.com/00_/status/1313216904186802176

*6:なお、5にはローンをカウントしない。これには少し安心した。

*7:実際の申請プロセスではなかなか一瞬で承認には辿りつかなくて不安になるのだが、Chase Approval Guide https://www.reddit.com/r/churning/comments/65vg85/chase_nonautomatic_approvalreconsideration_guide/ を読むと安心できる。

*8:Paypalのカードは審査もゆるそうでかつ海外手数料も無料なので魅力的だったが、Paypalが使えるサービスをあまり利用していない僕にとっては キャッシュバックがPaypalのクレジットでしかもらえないのが微妙だった (Paypal creditは銀行に無料でtransferできるので問題にならないそうです) ので、Citibank Double Cashというカードを使っている。それから、yusk_ さんのまとめにはフラット2.5%のカードも紹介されているが、invitation onlyなので除外している

*9:ただ、最初に作ったBank of AmericaのCash Rewards Credit Cardは3%カテゴリが四半期を越えて固定できるのでギリ許容範囲で、少なくとも食事のキャッシュバックにはこれを使っている。今はたまたまPlatinum tierにいるので50%ブーストがかかり、食事をする度に4.5%キャッシュバックされる

*10:厳密には、Amazon Prime Rewards Visa Signatureは申請時にAmazonのPrime会員が必要なのでそこに年会費が存在するけど、半年free trialでPrime会員になっているだけで、キャッシュバック率2%上昇だけ見ると年会費は割に合わないので、半年後は無料で使っているかもしれない

*11:夢のある話だが、当たり前だけどこれは極端に話を単純化しているだけで、本気で毎年そうなる可能性が高いと思ってるわけでは全くない。この後に現実ランドの話をしている。

*12:まあ実際には資産の99.6%が株なのは流石に不便だったので、僕は株価が下がる前に全部売っていた。運が良かった。

*13:そういうスリルを味わうのが趣味な人はこの記事の方針の想定には含まれていないので、個別株をやりたい人は好きにしたら良いと思う。

*14:何故市場平均を目指すべきかは https://hayatoito.github.io/2020/investing/ が参考になる

*15:これは前述の平均7%の利回りだったVTSAXがメインのもので、リスクの中和のためにInternational StockとBondが使われている。例えばUSの市場は縮小したけど中国とかが世界の市場は拡大させたみたいなケースで損を少し抑えたり、そもそもStockが下がっている時はBondが上がっていたことが多いのでそれでリスクを抑えるといった効果が期待できる。なお、何故USの市場がメインかというと、もちろんUSに住んでるから手数料が低いというのもあるが、1994年以降S&P 500は743%上昇したけどUS以外のStockは237%しか上がってなかったという程度には過去にUSの市場が一番伸びてるからリターンの期待値が高いというのが大きい。

*16:https://www.amazon.com/dp/B07DH1QYJK/ という本でも、Merrill LynchからVanguardに口座を変えたのはthe best financial decisionだったと書いてある。Merrill Lynchに資産をつっこんでおくとBank of Americaのクレカのキャッシュバック率を上げられたりするのだが、手数料がもっと安いところで投資するのとトータルで比較したら多分損をすると思われる

ベイエリアは東京より儲かるのか

サンフランシスコベイエリアでのITエンジニアの給料は東京より高いが、税金や物価も高いと言われている *1 。ではどちらに住む方がより多くの金が手元に残るのだろうか。

僕がベイエリアに移住してからちょうど1年が経ったので、僕が東京とベイエリアそれぞれにいた頃の出費やタイトルでどのくらい家の収支に差が出るのかということをまとめてみる。なお、この記事を書いている時点で 105.60 円/ドル なので、ドル円の変換をする際はこのレートを用いる *2

収入

基本給

ベイエリア 東京
$153,600 913万円

GitLabは同社の世界各地での待遇計算基準を 公開 しており、地域間の差異を公平に計算するには割とよくできたベンチマークなのでここの年収をそのまま使う。計算に使われる location_factors.yml では、日本の給与はサンフランシスコの 56.3% になっている。

Calculator に僕の現在のタイトルである Backend Engineer, Senior をいれると、Minimum Annual Base Pay が San Francisco で $153,600、Japan 全体で $86,477 (現在のレートで 913万円) となるのでこの給料を使う。なお、他のとある会社でのベイエリア移住直後の給料 も大体同じであった。

見出しは年収としたがこの額はBase Salaryに過ぎないため、例えば基本給の10%程度ボーナスがつくと東京での年収は1000万円強になる想定。

月手取り

ベイエリア 東京
$9,536 49.3万円

僕の収入が上記のものに最も近かったころの給与明細において、月あたりの「手取り/基本給」の係数がベイエリアで 0.745、東京で 0.648 だったため、雑にこれを 上記の年収 / 12 に掛けている *3 。この係数には以下の要素が影響している *4

天引き

所得税

ベイエリア 東京
税率 22% 33%
年控除額 $24,800 153.6万円

US の Federal Income Tax は married couples filing jointly の場合 standard deduction が $24,800 で、Marginal Tax Rate は収入が $80,250 ~ $171,050 の場合 22% になる *5日本の所得税 は年収 900万 〜 1800万 では控除額 153.6万円、税率は 33% になるが、様々な控除の結果「課税される所得金額」が900万を割る場合は23%でUSとあまり変わらなくなる。

表の見比べ易さの都合 ベイエリア / 東京 と書いたが、これはアメリカ国内と日本国内それぞれで共通である。

住民税

ベイエリア 東京
税率 10.3% 10%

カリフォルニアの州税は、State Income Tax が married filing jointly で収入 $115,648 ~ $590,746 の場合 $5,091.82 + 9.30% of the amount over $115,648 で、State Disability Insurance Tax が 1% 取られるので税率を雑に足して 10.3% としている *6東京都の区民税 は税率 10% + 定額 5000円 である。

年金

ベイエリア 東京
報酬比 8.65% 9.15%

US における厚生年金に相当する Social Security Tax は税率 6.2% *7 で、高齢者の医療に使われる Medicate Tax は税率 1.45% なので、これも雑に足して 8.65% とした。日本の 厚生年金 は報酬月額 63.5万円 以上での折半額は 59,475円 で、これは標準報酬 65万円 に対して 9.15% と計算されているが、それより大きな 913万円 / 12 = 76万円 から比較した実効レートは 7.82% になる。

保険料

ベイエリア 東京
月額 $469 3.2万円

USの会社で Kaiser HMO に夫婦と子供1人で加入し、Delta Dental と Vision の保険に夫婦で加入すると合計 $469.2 になる *8関東ITソフトウェア健康保険 は報酬月額 73万 〜 77万円 の時の保険料が 31875円。

支出

家賃

ベイエリア 東京
月額 $2,700 12.9万円

シリコンバレーのあまり治安が悪くないエリアで過去数年以内にリノベされた洗濯乾燥機 A/C つきでgroceryが徒歩数分の1ベッドルームの部屋を借りると、コロナ前は月 $2,700 ~ $3,200 くらいで、今は同じレンジで2ベッドルームの部屋が借りられる。コロナ前に $2,700 で借り始めた1ベッドルームよりは狭いがおおむね同じような条件の西日暮里の2DKの部屋が 12.9万円 だった。

光熱費等

ベイエリア 東京
月額 $378 2.2万円

今の家で水道、ウォーターサーバーの水 *9 、下水、ガス、ゴミ、電気、携帯回線、ネット、テレビを全部足して月 $377.77。東京で同じ月の水道、ガス、電気、携帯回線、ネット、NHK受信料を足して月 22290円。

交通費

ベイエリア 東京
月額 $587 0円

サンフランシスコでは車がなくても生活できるらしいが、シリコンバレーのあたりでは車がないと生活できない。車のローンが月 $430 *10 で、他にガソリン、オイル/タイヤ点検、洗車、DMVレジストレーション、車両保険を足して月 $156.55 くらいかかっている。東京は西日暮里〜東京間の定期券を会社負担で購入し、その区間だけで生活するような想定で0円とした。この差はとてもでかい。

食費

内食

ベイエリア 東京
月額 $537 4万

今週 Safeway (USのよくあるスーパー) と Mitsuwa (日本食スーパー) で消費した額を1週間の内食費とし、4かけて4週間分とした額が $537.44。東京での支払いは一部 (モバイルSuicaでない) Suicaを使っていて完全な履歴が残ってなかったため東京の額は妻の記憶を引用。

ちなみに、西日暮里で当時利用していたスーパーのチラシに載っていた品の中で今週のレシートにあったものを比較すると、以下のような物価の違いが見られた。日本食スーパーで材料を買うと、USで手に入りにくいものは海外から輸入されていて高かったりする。

ベイエリア 東京
大根 $1.61 159円
ねぎ $0.99 138円
ブロッコリー $3.99 213円
玉ねぎ $0.95 35円
豚切り落し肉 $7.59 626円
カラムーチョ $2.39 192円

外食

ベイエリア 東京
$217 1.3万円

ベイエリアで直近1か月でタピオカドリンク屋に4回、Jamba Juice に3回、Chipotleに2回、スタバ、Cold Stone、ポンデリング屋、最近オープンしたうどん屋、Five Guys、Shake Shack、マクドナルドにそれぞれ1回行った *11 合計が $216.76。これらに相当する回数、上野のタピオカ屋、スタバ、サーティーワン吉野家ミスド恵比寿の蕎麦屋 *12マクドナルドに東京で普通に頼んだ場合の額をシミュレートしたら合計12978円となった。東京の外食は安くて美味い *13

月収支

月手取りから支出の各項目を引いてくると、月あたりの収支は以下の通りになる *14

ベイエリア 東京
+ $5,117 + 28.9万円

$5,117 は現在のレートで 54万円 なので、同じジョブタイトルでもベイエリアで働いた方が月あたり 25.1万円 お得ということになる。

まとめ

いかがでしたか? 2020年のベイエリアはコロナで shelter in place となり、大統領によって USビザが大変な状況 に置かれ、10年に1度の規模のwildfire によって 赤い空と煙たい大気 に包まれた年になりましたが、お金はいっぱい貯まることがわかりました!

*1:https://gihyo.jp/dev/serial/01/alpha-geek/0031?page=2

*2:GitLab の Compensation Calculator が円の表示に使っているレート https://about.gitlab.com/handbook/total-rewards/compensation/#exchange-rates とは異なることに注意

*3:tax returnも考慮した額とそれほど乖離しないと仮定しているが、ここは本記事の中で最もいい加減な計算をしているので注意。後で真面目に計算し直すかも。

*4:税率は様々な控除が適用されてから掛けられるので、この月手取りに以下の税率を単純に掛けても実際の額が計算できないことに注意

*5:Effective Rateを計算すると少し違う税率になることに注意 https://twitter.com/hkmurakami/status/1311225597012488192

*6:こちらも Federal Income Tax と同様、実効税率とは異なることに注意 https://twitter.com/yusk_/status/1311498472235778049

*7:ただし $137,700 までしか課税されないため、実効税率はこれより低くなる https://twitter.com/yusk_/status/1311510628398292992

*8:医療費に関するコメントがあったので追記しておくと、例えば子供の出産の際日本だとお金がかかる麻酔を使ってもKaiserのおかげでお金がかからなかったりした。歯医者で日本でもアメリカでも保険が効かない治療、例えば金歯をいれるなどした時は、金歯代がネックなのでどちらでもほとんど変わらない額の負担だった。

*9:このあたりの水道水はフッ素が入っていて、健康への影響の懸念から天然水を飲み水にしている

*10:ここは本当は車の購入にかかる額全体を使用予定の期間で割るのが筋だと思うが、購入時の頭金は会社が移住時に補助してくれた額の一部でまかない、残りをローンで払っているという体の計算にしている

*11:コロナなのに外出しすぎでは? というのは否定しないが、うどん屋以外は全部テイクアウトで自宅か人気がない所で食べている

*12:交通費を0円にしたにも関わらず定期区間外の恵比寿の店を選んでしまったが、車のメンテ費に比べたら山手線の単発乗車賃は誤差ということで…

*13:とはいえこの額はコロナ期間の1か月なので、普通に外出できる期間はもっと外食費は高い

*14:なお、上記以外の出費はガジェットや電子書籍などでどの国から買ってもあまり値段が変わらないと仮定し、収支の比較から除外している。この額がそのまま貯金になるという意図ではなく、あくまで余剰の可処分所得という扱い。

US移住とブートストラップ問題

USに移住して4か月経った

入社直後から希望していたUS移籍を会社にサポートしていただき、去年の9/21にビザつきの状態で入国して、その後出張で出国は挟みつつもシリコンバレーで生活し始めてかれこれ4か月経った。 移住後の最初の2か月は右も左もわからず大変だったが、色々な人に助けられて今では落ちついて暮らせる状態になった。

自分用のメモを兼ねつつ、運が良ければ識者から知見が集まるよう、僕がどこで困ったか本記事に書いておく。US移住に興味がある人の参考にもなると思う。これはUSだとスーパーでかなり安く手に入る Ribeye ステーキ。

US生活ブートストラップ問題

クレジットヒストリ

USではクレジットカードやローンの利用履歴などに応じてクレジットヒストリーが付き、何かを契約する際そのスコアに応じて審査が行なわれる。クレヒスがないとクレカ、ローン、ネット、携帯、テレビ、家など様々なものの審査が降りない。つまりクレヒスがないとUSで生活することが困難になる。

問題は日本のクレカやローンの履歴は一般にUSのクレヒスにカウントされていないのでクレヒスが無の状態からどうにかクレヒスを付けないといけないことなのだが、クレヒスがないとクレカやローンの審査が降りないので一見すると詰んでいる。

おそらく一番有名な解決策はANA / JALカードを使うことで、どうやらこれは日本にいても申請できる*1クレカなのにUSのクレヒスが貯まるらしい*2*3。これから移住を予定している人は 今から使い始めておくと 移住の少し前 *4 に発行しておくと楽かも。ただ、一度移住を終えて不要になっても解約するとクレジットスコアが下がるので解約しづらい問題もある模様。

もう一つは、クレヒスがなくてもクレカを作らせてくれると評判の銀行 (Bank of Americaなど) に地道にクレカの申請を投げまくり*5、失敗した場合は最終手段として、あらかじめある程度金をいれておくかわりに審査がゆるいSecured Credit Cardを作るというのがある。僕は最初に2種類のクレカの申請をしたら両方弾かれたのでSecured Credit Cardを申請しかけたけど、並行して最初の2種類を再度申請していたのが片方通ったのでSecuredの奴はキャンセルした。なお枠が約15万円分とかになってしまう (今もそう) のでこの手段はあまりおすすめできない。

住所とSocial Security Number

SSN (Social Security Number) というのは日本でいうマイナンバーで、身分証明にはこの番号かこの下4ケタがよく使われる。会社、銀行、保険、家などを契約する時にはこの番号がないといけない。

SSNの申請する際身元を確認する必要があるためUSの住所が必要なのだが、その住所のために家を借りようとするとSSNが求められる。また、銀行口座かクレカがないと家は借りられないが、それらを申請しようとしてもSSNが求められる。完全に終わっている。

会社から手配されたコンサルの人にはSSNの申請フォームに会社の住所を書いておけと言われたので僕はそうしてSSNを発行した。が、my Social Securityのサイトとかを見ると住所は会社のオフィスにしてはならないみたいなのが書いてあるので多分正攻法ではなさそうだし、うっかりホテルなどで仮の住所を設定してそこに到着が遅れたらそこから出れなくなるか、最悪追い出されると身元を他の人に奪われる可能性もあるので、なんとも言えない。

これによってマンションを抑える時はSSNを持っていたけど、銀行とクレカの申請の時は、「さっき申請してきたからSSN届いたら提出するよ」で通った。申請する時に申請したレシートが貰えるのでそれで証明もできると思う。

車と運転免許

運転免許がないとレンタカーは借りられないし車も買うことができないが、運転免許の試験には自分の車を持っていく必要があり、その車の情報が免許に登録される。一体どうすればいいというのか。

日本の運転免許を既に持っている場合に限るが、これは日本で国際免許を発行しておくことでどうにかできる。日本の運転免許を持ってるなら、神田に行くと数分で国際免許が発行できる。これを持っていると、1年の有効期限の間、旅行で滞在している人はアメリカでも運転して良いことになっている。

ただし注意が必要なのは国際免許が基本的には旅行者向けのもので、州によっては居住者はルールが異なる点である。カリフォルニアでは、居住者になって10日以内にカリフォルニア運転免許に申請しなければならないと明記されており、これを最も保守的に読むと、マンションを借りるかSSNに住所を登録した日から10日までしか国際免許が使えないという話になる。*6 カリフォルニア運転免許を取るにはDMVというところで筆記試験と運転試験に通る必要があるのだが、運転試験の予約が10日で取れることはまずない (普通は取れても2〜3か月先の予約) ので、その間Uber / Lyftで繋ぐか、どうにかResidentでない状態を維持して国際免許で運転するかの2択になる *7 。なおシリコンバレー近辺で車なしで生活するのは無理である。

いずれにせよ、国際免許でレンタカーは借りられるし、日本人がディーラーをやっているガリバーUSAとかに行くと国際免許でも車が買えるので、それほど問題にならない。車を買う時に保険加入が必須で、その時も免許を求められるが、国際免許の情報で加入できた。

就労ビザ医療保険

医療保険に加入する際、SSNの提出が求められる。しかし、就労可能なビザでないと普通はSSNの申請ができないので、家族を医療保険に加入させる時に困ることがある。SSNを持てない人はかわりにITIN (Individual Tax Identification Number) を出すように書かれていたが、ITINの申請にはtax returnが必要で、移住直後にそんなものはまだ出していないのでSSNもITINもない家族が存在し得ることになる。

これが一番困った。加入の際に社の福利厚生サポートに電話した結果、適当な番号を埋めるよう言われそれで加入できたのだが、2019年の税金に関するフォームを医療保険の会社が作る際に再びSSNかITINの提出が求められた。ITINの申請について理解している同僚やHRがいなかったため3か月くらい特に解もなく困っていた。

結果的には、日本の確定申告のサポートのために手配された会社に質問し、そこのUS支社の人から「10月から住み始めたならまだnon-residentなのでITINはなくてもよく、次の時のtax returnの際に申請すればよい」といった旨の回答をいただいた。その年のUS滞在が180日以上じゃなければあまり気にする必要はないらしい。医療保険の方も、電話してみたらSSN or ITINは空でフォームを提出してくれと言われて、とりあえず2019年分はそれでどうにかなった。ITINは税金の話なので、HRではなく税金のプロに相談しないと問題が解決しないという学びも得られた。

US移住に関する雑多な知見

ブートストラップ感のあった問題は上記の通りだけど、その他にも4か月の間で得られた知見がいろいろとあるので適当に放流しておく。

日本食もある程度は食べられる

アメリカに旅行に来ると大体ステーキとかハンバーガーとかパンケーキを食べがちなのでそういう食事をするイメージがあった。ステーキとハンバーガーは実際結構食べてる気もするけど、毎日それだけというわけにもいかず、やはり普段日本食を食べられるに越したことはないという気持ちになる。特にこちらで普通に飲食店に入った時の米のクオリティが結構厳しい感じがする。

日本の食べ物を売っているスーパーがこの辺には三種類 (ミツワ、マルカイ、ニジヤ) あり、そこに行くとまあ日本で食べられるようなものが調達できる。そうじゃなくても近所のスーパーに日本食コーナーが割と広めに設置されていたりする。割と普通の値段で納豆が食べらるし、日本米も売っている。ステーキを食べる時も個人的には日本風の味付けの方が好みなので、Mr. Yoshida's Original Sweet Teriyaki ソース を買ったりしている。

外食だと、寿司とラーメンが無限にあるのは御存じかと思うが、東京でも割とおいしい部類のラーメン屋もあったり、まだ行ってないけど二郎系ラーメンもあったりする。この辺だと牛角吉野家やよい軒一風堂、Pepper Lunch *8 など*9の日本のチェーン店もある。

日本のテレビはあまり見れない

番組やってる国に限らずまあそもそもそんなにテレビ見ないんだけど、年末年始にちょっと特番を見たい気分になることもある。Comcastでケーブルテレビを契約しているが、そこに追加でお金を払うとテレビジャパンというのが見れるものの、これはNHKがやっている奴なので基本的にはNHKの番組が中心で、他局のが見たくてもないことの方が多い感じになる。日本のどこかの家にチューナーつきのサーバーを置いてくる人もいるけど、僕はそれが難しい状況だった。

あとはネットの動画サービス頼みという感じになる。日本ではAmazon Prime Videoを使ってたけどこっちではNetflixを見ている。日本っぽいコンテンツでも何故かUSでだけ配信されてたり、USっぽいコンテンツでも何故か日本でだけ配信されているといった不思議な状況がある。

シリコンバレーの家賃は想像ほど高くないかもしれない

前回の記事にも微妙に書いたけど、僕が懸念していたほど家賃が高くならなかった。 chibicodeさんが#地獄のサンフランシスコという話をしていたことがあり、2015年当時サンフランシスコは1ベッドルームで家賃の中央値が $3,530 であり、それが年に1〜2割上昇しているみたいな情報を目にした。マウンテンビューにいる同僚も大体そのくらいの家賃で住んでいると聞いていたので、自分の家賃もそのくらいすると思っていた。

が、シリコンバレーというのはサンフランシスコより割と南の方を指していて、Capital of Silicon Valleyを自称するSan Joseはそのスライドでも中央値が $2,220 なのである。この2つは全然額が違うと思うし、多分今の家賃もそこからめちゃくちゃ乖離しているわけでもない気がする。最近だとこういう話もある。そして既に子供がいる同僚と違い、まだ1ベッドルームで問題ない。前の記事の繰り返しだけど、アメリカの1ベッドルームは少なくとも2人なら十分暮らせる面積がある。

まあしかし家賃が安いところは大体治安が悪いか学区が良くないので安いというケースが多いので、お金は必要である。

病院では通訳がつけられる

医療系の用語は難しいし、妻が病院に通う際英語の通訳が必要になったのだけど、話で聞くところによると大体病院が通訳を用意していないといけないことになっているらしく、なんか部屋のスピーカーで通話越しに通訳が入れてもらえるということを学んだ。これは病院に電話する時も使える。まだあまり英語が得意でない家族が一大事の時でも安心できる。予約さえ取れれば、日本語が喋れるドクターもいる。

ビザつき初入国は審査が厳しい

重要な書類が入った本棚を航空便で別送しながらビザで初入国しようとしたところ、ビザ申請時に使った書類を見せないと入国を許可しないぞと言われた。普通に移民弁護士にも持ってくようメールで言われてたので不注意だった。SSNの申請を済ませたかった関係上どうしてもビザのステータスで入国したかったので「頼むよ〜」と言っていたら「次は持ってくるんだぞ」みたいな感じで通してもらえた。実際には2回目はビザスタンプだけで通してもらえた…

荷物の航空便はすぐ着くとは限らない

航空便なら2週間くらいで届くと言われていた荷物が1か月くらい届かなかった。割とすぐ届くだろうと期待していろいろ航空便で送っていたので、それが届くまで元から家具のある仮アパートから自分たちで抑えた部屋への引っ越しがなかなかできず、大分ストレスが貯まった。これから移住する人は、これだけあれば最低限暮らせるだろう、というレベルの荷物は手荷物で持っていくのが良いと思う。

永住権の申請は可能なら早めに始めたい

普通、ビザは3年くらい経ったら更新手続きが必要になるが、先にグリーンカードの手続きを終わらせてしまえばペーパーワークに使う時間が減って効率的な感じがする。 が、グリーンカードの書類の準備を始めてから受け取れるまでに2〜3年はかかるのが普通なので、入国してからすぐ手続きを始めないとその目論み通りいかない感じになる。直前に移住していた同僚もすぐにプロセスを始めていたと聞いて、僕も申請したい旨をHRの人に伝えたところ割とすぐ手配していただけた。まだ書類集めの最中だけど。

その他

他にも以下のようなことを書きたかったけど、記事が長くなりすぎるのでここでは短くまとめ、もし詳細に興味がある方がいればメンションなどしていただきたい。

  • Armが大企業なので移住のサポートが手厚く、便利だった
  • 企業型確定拠出年金の解約は原則退職時なのでUS移住と同時になってしまい、個人型への移管が面倒だった
  • ビザ申請者の年収は公開情報になっている
  • シャワーヘッド交換すると便利、あと多分浴槽は自分でカーテンかけるより最初からガラスの仕切りがついてる部屋の方が快適そう
  • 車は馬力がないと高速道路の運転に困りそうだと思ったが、割と皆それほど高くない車で生活している。駐車場が狭くて車を早速ぶつけてしまったので、運転が久々という人は一台目はなるべく安い車にしておくのがよさそう
  • 何とは言わないけど、VPNサーバーを立てるならIPv4だけじゃなくてIPv6もトンネルを通るようにしないと期待通り動かないことがある。
  • 大抵のマンションの敷地にはジムとBBQ場とプールがあるっぽくて面白い。うちはテニスコートもある。
  • 何年か前から維持してたSIMのタイムゾーンが違う地域の電話番号を使い続けてると早朝にスパムコールが来たが、この辺の地域の番号に変えたら変な時間にかかってこないかわりに量がかなり増えてしまった
  • 移住前後はUnion Bankを開設し、Transfer Wiseで最小限の円を送金した。Union Bankはもう解約した
  • こちらの銀行は定期預金とかでなくとも金利が年1.8%くらいのが普通にあるらしいのでそのうち開設したい
  • 鍵を使ってゲートを通らないと敷地に入れないようになっている方が玄関に変な勧誘が来にくくて便利らしいが、実際にはマンションの変な住人がやってくるので民度が重要
  • SSNに登録されている住所をオンラインで変更するにはmy Social Securityというサイトを使うが、2度もロックを解除してもらってリトライしたがアカウント作成に失敗した。他の人からもこれのアカウントを作れると聞いた試しがない

*1:日本向けのカードでヒストリがUSと共有されるわけではなく、日本のヒストリーを参照してUSのカードが発行できるという話らしい https://twitter.com/frsyuki/status/1219425958081384448

*2:僕が他の人から名前を聞いた時にはもうクレカを持っていたので申請しなかったけど、Premioというカードでもいけるそう https://twitter.com/suztomo/status/1219259746122899456

*3:Amexも日本のカードがあると移行できるらしい https://twitter.com/jmuk/status/1219332788152725504

*4:例えばANA CARD USAは渡米90日前から申し込み可能とのこと

*5:この時、オファーレターやpay stubなど、収入を証明する書類が信用の根拠になる。また、同時に銀行を申請している場合は、最初に銀行にいくら入金したかが見られているように感じたが、後者は気のせいかもしれない。

*6:が、Residencyがestablishされる条件は正確にはもっとゆるい可能性があると思う

*7:記事投稿時点では無意識に選択肢から外してたけど、仮免はDMVに早朝に並ぶなどするとすぐ取れて、かつ隣に免許持っている人を乗せると運転できるようになる。その同乗者は運転試験の時は必ず必要だけど、それまで生活している間いつも同乗してくれる人を見つけるのはなかなか大変そう。

*8:いきなりステーキ系列のいきなりステーキじゃない奴

*9:記事投稿後、リンガーハットもあるというリプライをいただいた

2019年にやったこと

ハイライト

  • 会社でSREからバックエンドチームに移籍
  • シリコンバレーに移住し、生活の基盤を整えた
  • RubyJIT開発を継続し、その参考にすべくJVMの実装を少し勉強した

発表

RubyJITの話を伊東で1回、東京で2回、博多で1回、USで1回、ロシアで1回の計6回話した。 今年はかなりいろいろ試した割にはなかなか成果が乏しい感じだったので、来年はバーンと成果を出していきたい。

英語での発表

年々少しずつながら多少は英語で話をするのに慣れてきた気がする。 割と自分が英語で話してる動画がたまってきたけど、最初に比べるとマシになったと信じたい。

去年書いてなかったけど、英語のPodcastにも2回出ていた。

仕事 / US生活

2018年は1年間SREチームで主にPythonを書いていたが、2019年は年明けからバックエンドチームというところに移ってKotlinを書いている。 Rubyは常に書いていて、入社後3回目となる rails new もした。

バックエンドチームの中ではストレージチームというサブチームにいて、TDで動いているクエリエンジンのストレージに関連したサービスのメンテナンスをしている。クエリの最適化をするために必要なメタデータを提供する下準備として、その基盤となる部分をでかいRailsからKotlinでDropwizardのサービスに切り出すということをやっているが、結合箇所が比較的多く大変なのと他にもいろいろ仕事がある関係でまだそれをやっている。次のクオーターで区切りをつけたい見込み…

サイドプロジェクトとしては、Xenial移行がパフォーマンス問題で難航してた奴をやっつけたり、Chefでデプロイしていたレガシーサービスを mitamae on CodeDeploy でデプロイするように移行したりした。mitamaeは全社的に使っているというよりは、割とChefのコードがあって素のCodeDeployに移行するのが大変 + トラフィックも多く移行リスクが高いようなサービスを安全に移行するために使っていて、歴史の長い3つのサービスで使われている。地味に成果物がいくつかオープンソース化されている。

入社時から希望していたUS移籍が叶い、妻と一緒にUSに移住した。US移籍が退職のち入社扱いだったので9月に有給を消化しまくり、10月からマウンテンビューオフィスで働いている。Armオフィスがサンノゼにありそちらに近くしようと考え、サンタクララのほぼサンノゼみたいな位置に住んでいる。同僚は月4000ドル前後の家賃を払っている人が多い中、割と安めのエリアの1ベッドルーム *1 なので家賃は月2700ドル弱。マウンテンビューは遠いので車通勤しながら Rebuild.fm の消化が捗る。

東京オフィスにいる時は英語だけ喋る同僚が近くにいて英語で会話する機会が割とあったが、こちらのオフィスで僕が関わるエンジニアが大体日本語を話せるので、仕事中あまり英語を話さなくなった。が、Zoomで英語を話す機会が週2〜4回あるし、プライベートで外にいる時に英語を使うので英語を話す時間はトータルでは増えていると思う。

ブログ

書きたいなあと思いつつ書いてないネタがまだ3つくらいあるんだけど、コードを書くのに比べて文章を書くのが大変面倒なのであまり書かなくなってしまった。かろうじて書けたのはこのあたり:

JVMの奴は本当はOpenJDKのVMJITの実装がCRubyと同じレベルでスラスラ読めるところまで行きたかったけど、独力ではちょっと大変だったので一旦やめた。Ruby Hacking GuideとかRuby Under a MicroscopeのOpenJDK版みたいな奴 (特にVMJITの部分が解説されているもの) をご存じの方がいたらご共有ください。

OSS活動

新作は習作のJJVMだけ。 一方既存のOSSのメンテを割とがんばっていたので、思い入れのあるものをご紹介:

2020年は

2019年が全く目論み通り行かなかったので… 今度こそJITRailsアプリが高速化できるようにしたいですね!

あとは英語の勉強を継続してTOEFL iBTで100点越えたいと思っている。

*1:一番小さい単位だけど、東京の2DKより広いのがほとんど

Rubyで最速のテンプレートエンジンを作る方法

HamlitというRubyで使うテンプレートエンジンをメンテしてて、ちょっと前に思いついたけどこれまで実装してなかった最適化のアイデアを昨日それに実装したので、それについてちょっと書きたい。

github.com

StringTemplate というテンプレートエンジン

amatsuda/string_template というテンプレートエンジンがあって、 これは "the fastest template engine for Ruby" であると主張されている。

もう2年も前の話になりつつあるが、今でもこれは最速だと思う。何故か?

String Interpolation を使った生成コード

Rubyのテンプレートエンジン」というのは例えばERB, Haml, Slimとかがあるのだけど、 これらは .erb, .haml, .slim ファイルを裏側でRubyのコードに変換しevalすることで動作している。

Railsなどの用途ではRubyのコードにコンパイルするのは最初の一回で良いので、 それをevalする時の性能が重要なのだけど、StringTemplateでは以下のようなテンプレート hello.string があると、

hello, #{ @world }
hello, #{ @world }
...

以下のようなRubyのコードを生成する。

%Q\0hello, #{ @world }
hello, #{ @world }
...\0

%Q\0 ... \0 というのは、テンプレート内容とコンフリクトしないようデリミタにヌル文字が使われている文字列リテラルで、 要するに " ... " と同じで、#{ } のようなString Interpolationが使えるだけの一つの文字列リテラルになっている。

他の生成コードパターン1: String Buffer

この "hello, "@world を連結しまくる方法はString Interpolationに限らない。これと同様のテンプレートをERBで書くと

hello, <%= @world %>
hello, <%= @world %>
...

で、これは

_erbout = +''; _erbout.<< "hello, ".freeze; _erbout.<<(( @world ).to_s); _erbout.<< "\nhello, ".freeze
; _erbout.<<(( @world ).to_s); _erbout.<< "\nhello, ".freeze
; ...; _erbout

コンパイルされる。@world行番号をテンプレートに合わせるために読みづらくなっているが、 一つのStringをつくり、そこに << で部分文字列を連結し続けるため、String Bufferと呼ばれている。*1

テンプレート全体をまるごと文字列リテラルにいれて動くシンタックスのテンプレートエンジンはStringTemplateくらいで、 普通はString Bufferのようなコードを生成することでテンプレート内での分岐を可能にしたりしている。

他の生成コードパターン2: Array Buffer

StringをBufferとして利用するかわりに、Arrayにいれておいて最後に join するという方法もある。

_erbout = []; _erbout.<< "hello, ".freeze; _erbout.<<(( @world ).to_s); _erbout.<< "\nhello, ".freeze
; _erbout.<<(( @world ).to_s); _erbout.<< "\nhello, ".freeze
; ...; _erbout.join

テンプレートが長くなるとString BufferよりArray Bufferの方が速くなる傾向にあるので、 いくつかのHaml実装*2はこのようなコードを生成している。 *3

何故String Interpolationが最速なのか

レンダリング時に @world の値を見て連結していくRubyのコードは主に上記の3パターンがあるが、 @world 部分をHTMLエスケープしない文字列連結*4において、 以下の2つの観点によりString Interpolationを使ったコードが最速になると思っている。

バッファのアロケーション

String Bufferだと、最初にバッファを作る際に事前に文字列のサイズを知ることが困難なので、最悪 << を呼ぶ度に文字列のバッファを拡張しないといけないことになる。 Array Bufferだと、join する時の文字列の長さは計算できても、Arrayのバッファ拡張は << を呼ぶ度に走り得るし、Arrayオブジェクトは他の方法では作っていないので、その分無駄になる。

String Interpolationでは、Ruby 2.5から @south37 さんによりバッファのプリアロケーションが実装され、各要素の長さの合計を事前に計算してから文字列用のメモリを確保するようになっており、アロケーションコストが O(1) になる。 また、要素数が少ないときは元の実装の方が速いらしく、状況に応じて適切に最適化がスイッチするようになっている。

メソッド呼び出しの数

StringやArrayの <<VMが特化命令を持っているため通常のメソッド呼び出しに比べてオーバーヘッドが軽いが、 他の to_sjoin は通常のメソッド呼び出し分のオーバーヘッドがかかっている。*5

String Interpolationだと、interpolateされたオブジェクトはVMのchecktype命令でStringかどうかをチェックし、Stringじゃなかった場合のみ to_s を呼ぶので、文字列がinterpolateされている時高速で、また文字列連結はconcatstringsという単一の命令内で完結するのでとにかく余計なメソッド呼び出しが発生せず速い。

もう一つの最速のテンプレートエンジン: Hamlit

StringTemplateが出るよりもさらに2年前、HamlitというHamlの高速な実装を作り、当時最速のテンプレートエンジンだった。

k0kubun.hatenablog.com

しかし、StringTemplateが出てから最近までの間、Hamlitで同等のテンプレートを書いてもArray Bufferのコードを生成するようになっており、StringTemplateの方が速くなってしまっていた。

実際、StringTemplateのリポジトリにあったベンチマークを、StringTemplateの機能相当に近付けてHamlitを参加させたベンチマークでは、Hamlit v2.9.5では*6以下のような結果になっていた。

Calculating -------------------------------------
              string    39.969k i/s -    100.000k times in 2.501936s (25.02μs/i)
              hamlit    34.498k i/s -    100.000k times in 2.898699s (28.99μs/i)

Comparison:
              string:     39969.0 i/s
              hamlit:     34498.2 i/s - 1.16x  slower

HamlはStringTemplateのスーパーセット

StringTemplateで使える #{ } は実はHamlでも完全にvalidなので、.string なテンプレートはシンタックスが衝突しない限り .haml としてもそのまま使うことができる。 なので、もしHaml実装が同様に高速なコードが生成できれば、わざわざStringTemplateな用途に別のgemをインストールしなくてもよくなるはずである。 ちなみにERBだと <%= %> になるし、Slimだと | を書いたりする必要があるので、それらは互換ではない。

しかも、StringTemplateのREADMEにはこう書いてある:

So this template engine is recommended to use only for performance hotspots. For other templates, you might better use your favorite template engine such as haml, or haml, or haml.

performance hotspotsにもHamlが同様の性能で使えれば、もし #{ } だけじゃなくて分岐とかしたくなった時にすぐできるし、便利なのではなかろうか。

Hamlit v2.10.0 でStringTemplate相当のコード生成を可能にした

なので、以下のPull Requestで、StringTemplate互換のテンプレートな時に単一のString Interpolationのコードが生成されるような最適化を導入した。*7

github.com

これにより、 Hamlit v2.10.0 では StringTemplateと同等の性能が出るようになった。 *8

Calculating -------------------------------------
              string    39.740k i/s -    100.000k times in 2.516339s (25.16μs/i)
              hamlit    39.719k i/s -    100.000k times in 2.517673s (25.18μs/i)

Comparison:
              string:     39740.3 i/s
              hamlit:     39719.2 i/s - 1.00x  slower

Haml実装でString Interpolationコード生成をする難しさ

これは、Array Bufferのコード生成器で単にString Interpolationを生成するように変えれば良い、という程度の簡単な話ではない。そんなことをしたら分岐ができなくなるし。

まず、HamlitではHamlとの高い互換性を実現するためにHamlのパーサーをそのまま使っている。以下のようなテンプレートは、

hello, #{ @world }
hello, #{ @world }
...

次のようなASTにパースされる:

#<struct Haml::Parser::ParseNode
 type=:root,
 line=nil,
 value=nil,
 parent=nil,
 children=
  [#<struct Haml::Parser::ParseNode
    type=:script,
    line=1,
    value={:text=>"\"hello, \#{@world }\"", :escape_html=>false, :preserve=>false, :keyword=>nil},
    parent=#<struct Haml::Parser::ParseNode:...>,
    children=[]>,
   #<struct Haml::Parser::ParseNode
    type=:script,
    line=2,
    value={:text=>"\"hello, \#{@world }\"", :escape_html=>false, :preserve=>false, :keyword=>nil},
    parent=#<struct Haml::Parser::ParseNode:...>,
    children=[]>,
   ...
  ]>

せっかく元のテンプレートではそのままString Interpolationに使えそうな感じになってるのに、 入力がわざわざ各行で別の文字列リテラルに分解されている。これはテンプレートエンジンが行番号を維持しながらコード生成をする必要があるため、このような挙動にすることによって後続のコンパイラの実装を楽にしているのだと思う。

しかもこれは任意のRubyスクリプト (:script) として文字列リテラルを抱えているので、これを受け取ったコンパイラはまずRubyスクリプトをパースして、それが文字列リテラルだった時のみ、連続した文字列リテラルを結合するということが必要になる。

そして上記の通り行番号を維持する必要があるため、コード生成器で改行するための特別な中間表現を文字列リテラル内の改行と交換する必要があったり、またもしStringTemplateと互換でないテンプレートも最適化したいなら、既にトークンがバラバラの中間表現になった世界で、どの改行は文字列リテラル用のものなのかを適切に判別しないといけない。

どうやって単一のString Interpolationにコードを最適化するか

HamlitではTempleというテンプレートエンジンフレームワークを使っていて、 先ほどのASTをコンパイルしていくつかのフィルタを通すと*9以下のTemple中間表現になる。

[:multi,
 [:dynamic, "\"hello, \#{@world }\""],
 [:newline],
 [:static, "\n"],
 [:dynamic, "\"hello, \#{@world }\""],
 [:newline],
 [:static, "\n"],
 ...
]

:multi は単に複数ノードの配列、:static はそのままバッファに繋げられる静的な文字列リテラル、:dynamic は to_s して繋げるRubyスクリプト*10、:newline は生成コード上の改行である。 [:static, "\n"]_buf << "\n" として生成され、文字列リテラル内での実際の改行ではなく \n になるので、生成コードの改行は通常 [:newline] だけで行なわれる。

さて、これを見ると "\n""hello, " 部分が分かれているのが無駄だが、これらを結合する最適化はHamlit v2.9 の時点でも入っていた。これはまず StringSplitter というフィルタ*11をかけると、RipperというRuby標準添付のパーサを利用して以下のように :dynamic 内の文字列リテラルを分解でき、

[:multi,
 [:static, "hello, "],
 [:dynamic, "@world "],
 [:newline],
 [:static, "\n"],
 [:static, "hello, "],
 [:dynamic, "@world "],
 [:newline],
 [:static, "\n"],
 ...
]

StaticMerger というフィルタをかけると、連続した :static を結合できる。

[:multi,
 [:static, "hello, "],
 [:dynamic, "@world "],
 [:newline],
 [:static, "\nhello, "],
 [:dynamic, "@world "],
 [:newline],
 [:static, "\nhello, "],
 ...
]

これでHamlのパーサーの困りポイントは解消され、比較的まともな中間表現列になっている。 さて、今回Hamlit v2.10.0 で導入した DynamicMerger というフィルタを使うと、これが

[:dynamic, "%Q\u0000hello, \#{@world }\nhello, \#{@world }\nhello, ...\u0000"]

に変換される。:dynamic 内の改行はそのままコードに出力されるので :newline 相当の働きをし、行番号は維持されている。これをコード生成器に渡すわけなので、StringTemplate同等の機能しか持たないコード生成器*12に渡せば、この文字列リテラル一つだけが生成される。めでたしめでたし。

DynamicMerger の中身がどうなっているかというと、:multi の要素の部分列が以下の条件を全て満たす時に、その範囲にのみ上記のような変換を行なうようになっている。

  • :static, :dynamic がそれぞれ1つ以上含まれる
  • :static の \n の数と :newline の数が一致する
  • :dynamic のコード内に改行がない

ちなみに、 StringSplitterDynamicMerger のように、to_s しないString Interpolationと :static, :dynamic を相互変換するのは String#to_s がモンキーパッチされてると等価ではなくなるんだけど、 まあこれで文句を言ってくる人がいたらコンパイル時点でそれが再定義されてるかどうかチェックして必ず to_s を呼ぶようにすればいいかなと思っている。*13

String InterpolationとArray Bufferのハイブリッドなコードの性能

DynamicMerger で遅くなるケースはほとんどないと思っていたのだけど、 「:static, :dynamic がそれぞれ1つ以上含まれる」という条件は少しチューニングの余地があるとリリース後に気がついた。*14

コード生成器にArray Bufferを使う時、例えば元々以下のようなコードを生成していたのが、

buf = []
buf << 'hello, '
buf << @world.to_s
buf.join

以下のように部分的にString Interpolationで結合すると微妙に遅くなってしまう。*15

buf = []
buf << "hello, #{@world}"
buf.join

じゃあArray Bufferを使っている時は DynamicMerger を使うべきではないかというとそんなことはなく、例えば :dynamic が2つある以下のものは元のコードより速くなった。*16

# before
buf = []
buf << @world.to_s
buf << 'hello, '
buf << @world.to_s
buf.join

# after
buf = []
buf << "#{@world}hello, #{@world}"
buf.join

なので、次のバージョンとかで、:dynamic を2つ以上要求するなど DynamicMerger の適用条件を少し厳しくしようかなと思っている。

まとめ

Hamlitを使ってない人、速度に妥協していませんか。 GitLabMastodonもHamlitを利用しています。

*1:出展: https://github.com/judofyr/temple/blob/master/lib/temple/generators/string_buffer.rb

*2:faml.gem と hamlit.gem のこと

*3:余談だが、ERBでもArray Bufferを使おうとした https://github.com/ruby/ruby/commit/ec7a964dca57821d2d7a36f168c2355a46a76ca2 ことがあるが、ERBの内部実装に強結合なライブラリがいくつか発見されrevertされた https://github.com/ruby/ruby/commit/0516a3378f03e8563350b8c4fe94ac3f9e9c9f75

*4:StringTemplate はinterpolateされた値のHTMLエスケープをサポートしていない

*5:Array Bufferでは一見 to_s を飛ばしても動きそうに見えるが、Array#join は to_str が存在する時はそちらを呼んでしまうので、互換性上明示的に to_s を呼ぶ必要がある

*6:Ruby 2.6.4, ActionView 6.0.0, Erubi 1.8.0, StringTemplate 0.2.1

*7:厳密には、Array Bufferの生成器を使っている時に to_s の呼び出しと _buf への代入が余計に生成されていて、それをなくす方法 https://github.com/k0kubun/hamlit/pull/147 も考えたが、そもコストはほぼ無だと思うのでそのままにした

*8:ベンチマークコードと、Hamlitのバージョン以外の条件はさっきと同じ

*9:わかりやすさのために、実際と少し違う順序でフィルタを通した結果を書いているが、やっていることは同じ

*10:ちなみに、記事内でテンプレートの分岐に言及しているがそれは :code で実現されており、:dynamic を文字列のinterpolationとすることは問題ない

*11:これは僕が発明した https://github.com/judofyr/temple/pull/96

*12:これは例えばHTTP Streamingサポートのための ActionView::OutputBuffer や、html_safe? 状態で結果を返すための ActiveSupport::SafeBuffer をラップしないコード生成器、という意味。これらはStringTemplateではサポートされていない

*13:つまり、速度の都合eval時にはチェックしたくないので、コンパイルしてから生成コードをevalするまでの間に初めて再定義されるケースは諦めたいという話

*14:というか、当然リリース前に考慮してマイクロベンチを書いてチェックしてたが、そのコードに少しミスがあって正しくチェックできてなかったのだった

*15:https://gist.github.com/k0kubun/4329c599685f467b212b565bb561743b

*16:https://gist.github.com/k0kubun/9c2c705be681c98984be97ad6a5b96bd