- incident.ioは開発者ノートPCをM3に切り替えるべきか判断するため、体感ではなくGoのビルド時間を基準にし、ローカル開発のフィードバックループの実データを収集
- 既存のGoホットリローダーでは必要な値を得にくかったため独自ツールを作成し、プラットフォーム・メモリ・電源状態・ビルド段階・トリガーしたファイル・総所要時間といったビルドイベントをデータウェアハウスに投入
- 約25k件のビルドから失敗・キャンセル・バッテリー駆動ビルドを除外した後、成功ビルド12,525件を分析し、AC電源でのビルドがバッテリー駆動より速いという統計的差を確認
- 結果としてM1ユーザーはビルド完了までほぼ2分待つことが多く、M2はM1に対して大きな改善、M3はM2に対して段階的な改善と判明
- 総ビルド時間ではメモリ差は明確でなかった一方、リンカー時間では32〜36GB構成が有利で、incident.ioはM1マシンを36GB標準のM3 Proに置き換えることを決定
アップグレード判断基準は開発フィードバックループ
- incident.ioの全開発者は開発作業用にMacBookを使用
- Appleが2023年10月にM3 MacBook Proを発表した後、CTOのPeteはアップグレードの価値がデータで証明されれば置き換えると表明
- チームはM3へのアップグレード可否を判断するため、3つを準備
- カスタムGoホットリローダー
- 開発者ノートPCのビルドテレメトリー収集
- OpenAIの最新モデルとコードインタープリターを活用したデータ分析
- 開発者生産性そのものを定量化するのは難しいが、incident.ioは高速なフィードバックループが開発者効率に重要だと考えている
- ローカル開発で頻繁に繰り返されるフィードバックループは次のとおり
- Goモノリスのコンパイル
- APIクライアントやインターフェースなどのコード生成
- フロントエンド・モバイルアプリのホットリロード
- incident.ioの開発者はノートPC上でincident.io環境全体をローカル実行し、コード変更から実行まで30秒未満のフィードバックループを維持
- Goアプリはコードベースがほぼ100万行に達しつつあり、頻度が高くコストも大きいGoコンパイルがMacBook性能比較の指標として選ばれた
ビルドテレメトリーの収集方法
- incident.ioは初期のGitHubリポジトリ作成時点から、Goホットリローダーとしてcodegangsta/ginを使用してきた
- 代替ホットリローダーも検討したが、ビルド時間分析に必要なテレメトリーを提供するツールは見つからなかった
- 各ビルドで収集したかったデータは次のとおり
- システム次元: M1/M2/M3プラットフォーム、総メモリ量など
- ランタイム指標: OS、メモリ使用量、電源ソース、バッテリー残量など
- ビルドテレメトリー: 総所要時間、Goビルド段階、ビルドを引き起こしたファイルなど
- 用意された代替手段がなかったため、
main.goから始めた独自ツールを作り、Macの各種バイナリ出力を実行・解析して必要な値を抽出
memory_pressure
docker
sysctl
pmset
- 関連コードはGistで公開されている
- システム・ランタイム収集器を作成した後、Goビルドコマンドをラップしてリンカー・コンパイルなど段階別時間とビルドトリガーファイルを収集
- 最終的なホットリローダーは既存の
make runターゲットから実行され、エンジニアリングチームには見えない変更だった
- ビルドが終わるたびにテレメトリーイベントをHTTPエンドポイントへ送り、FivetranのWebhookレシーバーでデータウェアハウスに投入
OpenAI Assistantを使った分析フロー
- 数週間かけて十分なデータセットを蓄積した後、BigQueryから
select * except(payload) from developer__build_eventsの結果をCSVとしてエクスポート
- OpenAI Assistantsに目的を説明するプロンプトとCSVファイルを提供
- 実験的モデル
gpt-4-1106-previewとコードインタープリターを有効化し、データ分析に利用
- ビルド時間は同一システムでも変動が大きく、Goコンパイラのキャッシュ影響も大きいため、プラットフォーム別平均だけを比べても公平ではない
- キャッシュのないM3 Maxが、キャッシュのある古いIntel MacBookより遅く見えることもある
- 分析は単純な平均比較ではなく、ビルド条件を整理し、プラットフォーム・メモリ・電源状態を分けて見る方式で進められた
データ整理と公平な比較条件
- 全体のデータセットは約25k件のビルドで、1日のさまざまな時間帯・ノートPC・条件から収集された
- 公平なプラットフォーム比較のため、次のビルドを除外
- 失敗またはキャンセルされたビルド: 完了していない作業であり、ビルド速度比較には不適切
- バッテリー駆動ビルド: OS Xがバッテリー寿命のために性能を制限する可能性がある
- 失敗ビルドを除外した後、成功ビルドは12,525件となった
- AC電源とバッテリー電源のビルド性能差は、主にM1 ProとM2 Maxを中心に比較
- 統計テストではAC電源ビルドの平均時間のほうが低く、p-valueは約0.0014だった
- 以降の分析では成功したAC電源ビルドのみを使用
Goビルド時間が揺れる理由
- incident.ioのGoモノリスはビルド性能を継続的に観察する対象であり、ハードウェア購入と同じくらいビルドプロセスそのものの削減・調整も重要
- Goプロジェクトは複数のパッケージで構成され、Goコンパイラは変更があると判断したパッケージだけを再コンパイルするようキャッシュを活用する
- incident.ioアプリは依存グラフが広く、基盤モジュールが少なくなるよう設計されており、ほとんどの変更がグラフ全体の再コンパイルにつながらないようになっている
- ビルドの種類はおおよそ4つに分かれる
- 即時完了、3秒未満: Goコンパイラと無関係な変更で、キャッシュ済みバイナリを使える
- 高速ビルド、30秒未満: 依存パッケージが少ない単一パッケージの変更で、ほとんどキャッシュを再利用し、主にリンクに時間が使われる
- 中間ビルド、30秒〜1分: 一部の下位パッケージ依存を持つ機能パッケージを修正したが、大半は再利用可能
- 低速ビルド、1分超: 基盤
domainパッケージに型を追加し、アプリの全パッケージを再コンパイルする必要がある
- プラットフォーム比較ではこうしたビルドの性質差を考慮する必要があり、すべてのビルドを一括で混ぜると apples to oranges の比較になってしまう
M1、M2、M3の比較結果
- 成功したAC電源ビルドのみを対象に、まずM1 ProとM2 Maxを比較
- M2 MaxはM1 Proよりビルド速度で大きく上回ったが、両機はチップセットだけでなくメモリ構成も異なっていた
- 成功ビルドイベントのプラットフォーム・メモリ別分布は次のとおり
- Apple M1 Pro 16GB: 5,235件
- Apple M2 Pro 16GB: 1,927件
- Apple M2 Max 32GB: 3,842件
- Apple M3 Pro 18GB: 321件
- Apple M3 Pro 36GB: 899件
- Apple M3 Max 36GB: 301件
- M1 Pro 16GBとM2 Max 32GBの比較は、メモリ差のため完全に公平ではなかった
- M2 Pro 16GBとM2 Max 32GBを比較すると、32GBメモリが総ビルド時間に与える影響は小さいように見えた
- M2 ProとM2 Maxは概ね同じチップであり、Maxには追加の高効率コアが2つある
- そのコアは性能コアの約1/5程度であり、Goプログラムのコンパイルへの寄与は小さいと判断された
- M3評価のため、次の3台を購入
- M3 Pro 12コア、6性能コア + 6高効率コア、18GB
- M3 Pro 12コア、6性能コア + 6高効率コア、36GB
- M3 Max 14コア、10性能コア + 4高効率コア、36GB
- M3 Pro 18GBと36GBのビルド時間グラフは似ていたが、M3データは他プラットフォームより少なかった
- 3秒未満の非常に高速なビルドを除外してM3 ProとM3 Maxを比較したところ、M3 Maxは標準のM3 Proより60%高い価格を正当化するほど目立つ改善を示さなかった
- 全体判断は次のとおり
- M1ノートPC利用者はビルド完了までほぼ2分待つことが多い
- M2はM1に対して大きなアップグレード
- M3はM2に対して段階的な改善
- M1利用者は標準のM3 Proへアップグレード
- M2利用者はアップグレード不要
メモリはリンカー時間でより明確に現れる
- 総ビルド時間の比較では、16〜18GBから32〜36GBへ増やしても有意な改善は大きく見られなかった
- 予想に反してメモリ効果がグラフに大きく現れなかったため、ビルド段階のうちリンカー時間を個別に分析
- テレメトリーイベントにはリンクとコンパイル段階の時間が含まれており、
build_stages.link.duration_secondsからlinker_timeカラムを作って分析
linker_timeをプラットフォーム・メモリ構成別に比較すると、別のパターンが見えた
- 32〜36GBメモリを持つM1・M2・M3マシンは、ほぼ常にリンクを20秒未満で完了
- 18GB以下のメモリ構成では、リンクが20秒を超えることがしばしばあった
- メモリ増設は総ビルド時間では分かりにくくても、リンカーステージでは有効であることが確認された
- 開発マシンからDockerを外す案も検討中で、低メモリ機ではDockerなしで利用可能なシステムメモリを増やし、リンク時間を改善できる可能性があるという解釈につながった
- モバイルアプリ開発ではシミュレータが多くのシステムメモリを消費するため、メモリ増設は将来への備えとしても妥当だと判断
最終決定と副次効果
- incident.ioはM1マシンを36GBメモリの標準M3 Proへアップグレードすることに決定
- M2マシンはすでに十分高速に見えるため、当面はアップグレードしない
- ノートPC購入判断に加え、開発環境とツールへの理解も深まった
- チームが得た成果は次のとおり
- 開発者マシン性能を測る良いベンチマークとしてGoビルド時間を見つけた
- 必要なメトリクスを追跡する独自のGoホットリローダーを作り、ほかのユーザビリティ改善も得た
- Goビルドが速くなる・遅くなる要因をよりよく理解した
- OpenAI Assistantsで類似のデータ分析課題を扱えることを確認した
- Appleチップの各ラインアップの改善をGo開発者視点で定量化した
- メモリは重要だが、総ビルド時間よりリンカー時間でより明確に現れる
1件のコメント
Hacker Newsのコメント
素晴らしい記事で、データの収集・分析方法も多様で良いが、各ノートPCを横に並べ、同じシナリオで計測用ビルドを走らせたほうが、はるかに簡単で正確だったように思う。
フルビルド、直近の変更分のインクリメンタルビルド、特定モジュールの再ビルドが必要なインクリメンタルビルドなどをいくつか比較したり、直近100件のGitコミットを順番に適用しながらインクリメンタルビルド時間を測るスクリプトを、1日以内に作れたのではないか。
会社全体の統計を集めるとバイアスが大きくなり得る。たとえば新人はM3、古くからいる社員はM1を使う可能性が高く、新人は小さな変更を多く行い、熟練者はコードの深い部分や複雑な領域を扱うためビルド時間が長くなるかもしれない。
だから分析自体は見事だが、サンプルに内在するバイアスを考えると、会社全体のデータ収集アーキテクチャを作る前に、各ノートPCで最近のコミットをベンチマークする単純な方法から始めるべきだと思う。
このデータを集めた理由は、機器間の比較もあるが、開発者のビルド時間の履歴データを蓄積し、ビルド性能を継続的に測定してリグレッションを検出するためでもあった。
ビルド時間が伸びているのを見ると、コードベースの構造を頻繁に調整してビルドを速くしている。
M3はM1よりビルドを30%速くできるかもしれないが、ネットワークビルドは15倍速い。開発者にM3を渡す代わりにネットワークビルドへ投資すべきだったかを検討できる。
独立にサンプリングされていないデータにt検定を行っているが、複数のデータポイントが別々の人から来ており、人によって作業が異なって計算要求量も変わり得るため、交絡要因が生じる。これはt検定の基本仮定に反しているが、コードインタープリタは指摘しなかった。
代わりに、ノートPCの所有者や勤続年数のような要素をランダム効果として入れる線形混合効果モデルを使えたはずだ。
それでもデータ自体は興味深く、特にRAMの部分が面白かった。キャッシュは強力で、RAMが多いことによる利点は人々が考えるより大きい。通常、必要量よりRAMが多いMacBookでは、余ったRAMの大部分がキャッシュで埋まっている。
1週間ほど集めれば実際の作業負荷の断面が得られ、そのビルドを各ハードウェア等級で繰り返し実行でき、後で新しいハードウェアにも再利用できる。
科学者として、コンピュータプログラマーたちのデータの扱い方は興味深い。
きれいなグラフを描き、ChatGPTで分析を非常に素早く自動化し、ChatGPTはかなりもっともらしいt検定を出していた。
しかしメモリとチップの種類による変動があったのに線形回帰を考えておらず、比較しにくいヒストグラムを描いていた。単純な平均とエラーバーで補足したり、重なりやシフトを見やすい累積分布関数(CDF)を使うこともできたはずだ。
一般的にはツールが示す方法に従ってデータを扱うが、これは分析、性能分析、可観測性ソフトウェア製品群ともかなり関係している。
平均的なソフトウェアエンジニアがCDFを知っているべきだと期待するのは、3Dグラフィックスのクォータニオンやシェーダー作成の基礎を知っているべきだと期待するのに近い。
あるいは分位点回帰も可能だ。M3 > M2 > M1という仮説があるなら、順序のある中央値に使う有名なJonckheere–Terpstra検定が、こうした擬似分析にはぴったりだったかもしれない。
例はこのページの最後のグラフを見るとよい: https://ggplot2.tidyverse.org/reference/stat_ecdf.html
堅実な分析だが、個人的な経験から一つ警告しておきたい
従業員2,000人規模の中堅ソフトウェア会社で開発生産性を高めようとして、新しいノートPCの代わりに開発スタックをAWSインスタンスへ移す案を検討した
結果として開発者4人ほどがフルタイムで張り付く数年がかりのプロジェクトになり、振り返ると費用対効果はなかった。完全にローカルな開発体験をクラウドで再現するのは、まだあまりにも難しい
だからノートPCをアップグレードしたほうがよいと思う
コードはノートPC上にあるが、DockerビルドやK8sデプロイなしでリモートサービスとリアルタイムに同期され、本当にローカルのように感じられる
特にコーディング中に統合テスト以上のものをすぐ実行できるので、commit-push-prayのサイクルを避けられる
そのためにGarden(https://docs.garden.io)を使っている。Gardenを使うかどうかにかかわらず、適切なツールがあれば、内部の開発ループにクラウドの力を活用するのはかなり素晴らしいものになり得る
経験を詳しく書いた記事: https://thenewstack.io/one-year-of-remote-kubernetes-develop...
ローカル専用版では不可能だったこともいくつも可能になった。例えば複数のブランチを行き来するとき、ローカルファイルを切り替える代わりにマシンを切り替えれば、作業切り替えの遅延がずっと小さくなる
何かをするのに200個を超える部品を立ち上げなければならない場合、そのうち数個とだけ連携する単一部分を作業するのも難しい
128コア以上、256スレッド以上のサーバーがある時代なので、ほとんどのソフトウェアには再びモノリスのほうが良いのではないか、という考えに傾いている
純粋なお金と時間の無駄だ。すべてのシステムコールをベンダー製の邪魔なソフトウェアでフックすると、多数の子プロセスを実行するUnix式ツールチェーンには悪いのだと分かる
GoogleやMetaのような大手テック企業では、大多数のソフトウェアエンジニアの開発環境はクラウド上にある
ローカルよりはるかに良い開発体験だ
iOS開発基準で、コストまで考慮して個人的に調べた結論はこうだった
M2 Proは良いが、10コアM1 Proと比べて改善幅はそれほど大きくない。XcodeBenchmark基準で136秒対120秒だ: https://github.com/devMEremenko/XcodeBenchmark
M3 ProはM3 Maxと差別化して売るために弱められた印象で、性能コアが6個しかないため、実質的にはM2 Proに近い
結局、少し使われた10コアM1 Proを買い、とても満足している。ベースのM3 Pro価格の半分にも満たない費用で性能の85%を得られたし、一般にCPUが少なくとも33〜50%速くならないと違いを体感しにくいという点も考慮した
M2 Proよりはるかに効率的で、性能も少し良い。ノートPCに私が求めるのはそういう部分で、メモリ帯域幅は特に使う場面がない
この記事で示された差ほど大きな差はなかった。言語やプロジェクトによって違うかもしれないが、同じコンパイルコマンドを並べてベンチマークしたとき、これほど大きな差は見なかった
コンパイルツールチェーンが違うので驚きではないし、Goのツールチェーンでも追加メモリがリンカー性能に役立つように、特定の仕様がビルド段階ごとに異なって作用するのが見て取れる
M3の性能が妙に制限されているという反応も何度か見たが、M4以降のモデルでは続かないことを望む
120Hzもあると良いが、AirのノートPCには入らなさそうだ
ChromiumとNode.jsの元コアコントリビューターで、現在はgRPC Core/C++のコアコントリビューターだが、ビルド時間が原因で大きく気になったことはない
作業中に関連する単体テストを再実行するためのインクリメンタルビルドである「インタラクティブビルド」と、実行しておいてコーヒーを飲んだりメールを読んだりする非インタラクティブビルドがある。ハードウェアの交換によって非インタラクティブビルドがインタラクティブに変わるのを見たことはない
個人用マシンは5年以上前のIntel i7と16GBメモリだが、WSLでNode.jsをリンクするにはメモリがもっと必要だと分かって16GBを追加した
仕事用ノートPCはTouch Bar付きのIntel MacBook Proで、生産性に大きな影響があるとは思わない。重要なのは画面サイズと品質、ストレージ速度だ。CPUの進歩よりも、インクリメンタルビルド速度や分散ビルド対応のようなビルドシステムの影響のほうが大きい。個人プロジェクトではBazelを使っている
コンパイルとリンクは実質的に即座に終わるべきで、コンパイル段階があることを意識しないほど速くあるべきだ
全プログラム最適化のような手法が入るリリースビルドは時間がかかっても構わないが、一般的なコンパイル/デバッグ/テストのループは即時にできるはずだ。システム言語のコンパイルはレガシーな理由で信じがたいほど遅いが、必ずそうでなければならないわけではない
BUILDファイルをいじるのに多くの時間を使っているうちに、普通のMakefileより価値があるのか疑問に思った。3年前の話なので、今の公開エコシステムはもっと良くなっているかもしれない
ストレージ速度はよく分からないし、うちのビルドはすべて強力なリモート開発マシンで動いている
記事のようにAIでデータ分析をしようとする人には、データをRやStataなどに入れて自分でクエリするほうがずっと簡単だと思う
コマンドはより短く正確で、何より再現性が高い
データ分析で最も難しいのは、データとそれを生み出したメカニズムを理解することだ。そのためには問題領域の因果モデルが必要になる
AIがその領域の別のデータで先に訓練されていなければ、有用な因果モデルを作れるのか分からない。そのモデルなしにデータを合理的に解釈するのは不可能で、現在のAIモデルが交絡、過度な外れ値の影響、興味深い効果修飾変数を検出できるのかも気になる
自分がやったときはPythonとpandasで、分析に使ったコードを見せてほしいと依頼できる
データをR/Pythonに入れて「xyzzzyをどうやるか」を検索して自分でコードを書くか、ChatGPTを使うかの違いだ
「すべての開発者がノートPC上で完全なincident.io環境をローカル実行し、コード変更から実行まで30秒未満のフィードバックループを得る」という部分が最大の成果に見える
スタートアップを少し手伝った場合を除けば、1台のマシンで会社全体の開発/ローカルインスタンスを実行できた会社はなかった
常にアクセスできない何かがあり、いつも落とし穴があった
こうしたひどい開発者体験に、なぜ人々がもっと怒らないのか分からない。最近の大学出身者は、自分たちが何を失っているのか分かっていないようだ
その世界を経験したことがない人は、どれほど良いものか理解できず、あらゆる形で正当化する
ただ昨年Snowflakeを追加したのだが、実際の問題は解決してくれるものの、その部分を反復開発するのはつらい
サポートすべきサービス数に対して線形で、サポートすべきエンジニア数に対しても線形だ。さらに相性の悪い多様なユースケースが生まれ、いつの間にかインフラチームが機能リリースのボトルネックになり、人々がそれぞれ別のやり方を使い始める
そのパンドラの箱が開くと、元に戻すのは事実上不可能だ。それでも開発サイクルを数時間・数日から数分に縮めることは、数分を25%短縮するよりはるかに重要だ
今のところはうまくいっている
筆者として、投稿してくれてありがとう
Goのコンパイルのプロファイリング、ホットリローダー作り、AIでビルドデータセットを分析することなど、いろいろな内容が入っている
結論として、M1はM3 Proにアップグレードする価値があり、テストではMaxは大きな差を生まなかった。M2はM3にかなり近く、私たちにとってはアップグレードする価値がなかった
質問があれば答えられる
そのコストが回収期間にどう影響するのかも気になる
あるいは、作業があまりに速く終わるため、実際の使用では差が出なかった可能性もある
アイデアは興味深いものの、データ分析の品質はかなり低く見え、実際に考えていることを学べているのか確信が持てない
特に M1 Pro から M2 Pro に移行したとき、20秒未満のビルドがあれほど劇的に増える理由が理解しにくい。コードコンパイル作業における両者の実際の性能差はおおよそ20〜25%程度
M3 マシンが M2 マシンより20秒未満のビルドが少なかったり、コア数が半分の M3 Pro が M3 Max より20秒未満のビルドが多かったりするのも、あまり筋が通らない
ノートPCの種類が違う人たちは通常、互いに異なる作業をしているなど、開発者の行動差がこうした差を生んだ可能性が高い
ざっと読んで得た観察としては、Go コンパイラは追加コアをあまり活用できていないようで、データをまとめる方法が根本的に扱いづらく、比較方法もヒストグラムと区間化された密度グラフが混在し、Y軸の範囲も異なっていて一貫性に欠ける
Mac はバッテリー駆動だからといって CPU 性能をスロットリングしない。本当にバッテリー駆動時にビルドが遅いのだとしたら、グラフだけでは断定しにくいが、「低電力」設定がオンになっているためだろう
少し横道にそれるが、他社はエンドポイント管理やセキュリティソフトウェアと開発者の生産性をどうバランスさせているのか気になる
うちの会社では、開発者ノートPCの Mac と Windows の両方で、バックグラウンドサービスを5つ以上動かしている。エンドポイント管理、権限昇格の横取り、TLS の横取りと検査、マルウェア対策、VPN クライアントが含まれる
この組み合わせは性能に大きく影響する。マシンで何をしていても、これらのサービスが CPU と入出力性能を食いつぶし、開発者たちはランダムなフリーズやカクつきを訴えてきた
ランサムウェアや知的財産の窃取が増えていることを考えれば、セキュリティが必要なのは理解できるが、開発者の生産性への影響を抑えつつセキュリティを提供する、より良い方法を見つけた会社があるのか気になる