2.16

View in English

2.16 パフォーマンスエンジニアリング

概要と動機

パフォーマンスエンジニアリングとは、直感ではなく測定を用いて、意図してコードを十分に速くする技芸です。本章は、コードとコンポーネントのレベル、つまり関数、ループ、データ構造、クエリ、メモリ割り当て、そして単一のサービスが時間をどう使うかで扱います。これは、システムレベルの性能(スケールアウト、負荷分散、キャパシティ、レジリエンス)を扱う3.5章の対となる章です。システムが遅いとき、3.5章は何台のマシンが必要かを問い、本章は、そもそもなぜ一台のマシンがそんなに多くの仕事をしているのかを問います。通常は両方が必要で、コードレベルの見方は、驚くほど多くのコストとレイテンシが実際に隠れている場所です。

大きなチームにとって、この規律が重要なのは、性能が静かに劣化するからです。単一のコミットがサービスを遅くすることはありませんが、それぞれがデータベース呼び出しや制限のないループを加える千の小さなコミットは遅くします。性能を測定し、予算化し、ゲートで守る共有の方法がなければ、顧客が不満を言うか、ローンチが溶けるまで劣化に気づきません。方法は、性能を、英雄的な消火活動から、守る日常的な特性に変えます。

企業にとって、性能はお金です。速いコードはマシンを減らし、クラウドの請求を下げ、過剰にプロビジョニングせずにレイテンシのサービスレベル合意(SLA)を満たせます。政府にとって、性能はアクセスです。弱いモバイル接続の古い電話で読み込めるページは、市民が給付の申請を完了するか、諦めるかの違いです。公共のシステムはまた、再現可能なベンチマークの証拠を必要とします。調達や監督機関は、数字を単に主張するのではなく、証明するよう求めるからです。

主要原則

  • 最適化の前に測定する。 ボトルネックは、推測した所にはほとんどありません。プロファイルしてから行動します。
  • 早すぎる最適化を避ける。 Donald Knuthの警告は成り立ちます。重要でないコードを最適化することは、明快さを犠牲にして何も買いません。
  • 「十分速い」を数字で定義する。 目標とパーセンタイルを伴う性能予算は、意見を合格か不合格に変えます。
  • 平均は嘘をつき、パーセンタイルは真実を語る。 ユーザーが感じるのは平均ではなく裾(p99)です。
  • アルゴリズムの勝利は微調整に勝つ。 より良い計算量のクラスは、定数倍の巧妙さをいくら重ねても追い越します。
  • レイテンシとスループットは別の目標である。 一方を改善すると他方を悪化させうるので、どちらを買っているかを知ってください。
  • 正直にベンチマークするか、しないか。 ウォームアップ、分散、代表的なワークロードが、本物の数字と虚構を分けます。
  • 性能をCIでゲートし、本番で観察する。 マージ前に捉えられた回帰は安く、ユーザーに捉えられたものは高くつきます。

推奨事項

まず測定し、一行に触れる前にプロファイルする

この分野で最も古いルールは、最も無視されるものです。最適化する前にボトルネックを見つけること。プロファイラ、つまり実行中のプログラムをサンプリングまたは計装して、時間とメモリをどこで使っているかを示すツールに手を伸ばします。CPU(どの関数がサイクルを燃やすか)、メモリとアロケーション(何がどれだけ頻繁に割り当てられるか。アロケーションの変動はガベージコレクションの停止を駆動するので)、I/O(ディスク、ネットワーク、データベースを待つ時間)をプロファイルします。フレームグラフ、つまり各ボックスが関数で、その幅が費やされた時間である積み重ねの可視化は、支配的なコストを一目で明らかにします。最も深いスタックではなく、最も幅の広いボックスを探してください。最大のコストを最初に最適化し、再測定し、予算に達したら止めます。これは9.2章のオブザーバビリティの実践につながります。本番のプロファイルは、ノートPCから行ったどんな推測にも勝るからです。

逆の誤りにも用心してください。Knuthの完全な言葉は、早すぎる最適化は多くの悪の根源だというもので、彼が意味したのは、読みやすいコードを想像上の速度のために犠牲にしたくなる、小さな非効率についてです。まず明快な版を書き、測定し、プロファイラが糾弾するコードだけを最適化します。

性能予算で「十分速い」が何を意味するかを定義する

速度は抽象的な美徳ではなく、達成するか逃すかの目標です。性能予算を設定します。「p99のチェックアウトのレイテンシは300ミリ秒未満」や「このエンドポイントはリクエストあたり1MB未満しか割り当てない」のような具体的な上限です。それをユーザーやビジネスが感じるものに結びつけ、平均ではなくパーセンタイルで表現します。平均は、本物のユーザーがいる遅い裾を隠すからです。リクエストの1%が5秒かかるなら、顧客の意味のある一部が苦しんでいる間も、平均はよく見えるかもしれません。予算は、チームに、共有された反論のない完了の定義と、回帰が目に見えて越える線を与えます。

微調整の前にアルゴリズムの効率に手を伸ばす

最大で最も安い勝利は、アルゴリズムの効率、つまり入力が増えるにつれて仕事がどう増えるかから来ます。それはビッグオー記法(増加率を分類する方法で、O(n log n)のソートは、O(nの二乗)のものよりはるかによくスケールする)で記述されます。10個の項目では見えない入れ子のループは、1万個で大惨事になります。ホットな関数を手で調整する前に、それが根本的にやりすぎではないかを問ってください。偶然のN+1クエリ、ハッシュ検索にすべき線形スキャン、メモ化できる繰り返しの仕事。これは2.13章のアルゴリズムの基礎につながります。定数倍の調整をいくら重ねても、誤った計算量のクラスは救えません。

レイテンシとスループットを区別し、裾を尊重する

レイテンシは一つの操作にかかる時間で、スループットは単位時間あたりに完了する操作の数です。それらは同じ目標ではなく、一方の最適化は他方を損ないえます。バッチ処理はスループットを改善しますが、バッチの最初の項目にレイテンシを加えます。並列ワーカーを加えるとスループットは上がりますが、競合を通じてテールレイテンシを悪化させえます。ユーザーが実際にどちらを必要としているかを決めてください。そして常に裾を見ます。p95とp99のレイテンシ、リクエストの最も遅い5%と1%です。規模が大きくなると、ユーザーは多くのリクエストを行い、裾に頻繁に当たるからです。パーセンタイルを報告し、それに対してアラートを出し、予算化します。

並列性の限界を知る

並列化するとき、アムダールの法則を思い出してください。プロセッサを加えることによる高速化は、直列に実行しなければならない仕事の割合によって頭打ちになります。仕事の10%が本質的に逐次的なら、いくらコアを増やしても10倍の高速化を超えられません。並行性(タスクが独立して進めるように仕事を構造化すること)と並列性(実際に同時に実行すること)は、競合状態から調整のオーバーヘッドまで、本物の複雑さを加えます。スレッドを増やせば救われると想定する前に、直列の割合を測定し、最も単純な正しい版がしばしば十分に速いことに正直であってください。

キャッシュとデータの局所性を使い、そのコストを尊重する

キャッシュ、つまり最近計算された、あるいは計算コストの高い結果の高速なストアは、持っている中で最も強力な性能の道具であり、最も危険なものです。コンピュータサイエンスの難問は二つ、キャッシュの無効化と命名だというPhil Karltonの皮肉は警告です。古いキャッシュは間違った答えを返し、無効化のロジックは微妙なバグが育つ場所です。意図してキャッシュし、有効期限を設定し、ヒット率を最適化する前に、正しさの筋書きを把握してください。最も低いレベルでは、参照の局所性、つまり一緒に使われるデータをメモリ上で近くに保つことが、CPUのキャッシュ階層を活用し、キャッシュミスをヒットに変えることで、アルゴリズムを変えずにコードを数倍速くできます。連続した配列は、このためにポインタをたどる構造に勝ります。これは3.4章のデータレイアウトの選択と交わります。

正直にベンチマークし、マイクロベンチマークを疑う

嘘をつくベンチマークは、偽りの確信を与えるので、ないよりも悪いものです。測定の前にウォームアップし、一回限りの起動やジャストインタイムコンパイルではなく、定常状態の振る舞いを計測します。多くの反復を実行し、一回の幸運な数字ではなく分散を報告します。現実的なデータサイズと分布を持つ代表的なワークロードを使います。おもちゃの入力でのマイクロベンチマークは、コードの本当の速度ではなく、コンパイラがあなたのテストを削除する能力を測っていることがよくあるからです。古典的な罠に注意してください。オプティマイザが未使用と証明して取り除く値、ランタイムが巻き上げるループ、ベンチマークでは温まっていて本番では冷たいキャッシュ。迷ったら、孤立した関数ではなく、経路全体を測定します。

CIで性能をゲートし、本番で観察する

性能を、パイプラインが守る特性にします。2.4章の戦略に性能テストを加え、主要なベンチマークや予算が閾値を超えて悪化したらビルドを失敗させる、回帰ゲートを設けます。これは、マージされる前に、じわじわとした劣化を捉えます。それから、9.2章のテレメトリで本番でループを閉じます。本物のレイテンシのパーセンタイル、アロケーション率、遅いクエリを予算に照らして追跡します。本番のトラフィックは、ベンチマークが想像したこともないケースを見つけるからです。

トレードオフ: 長所と短所

アプローチ長所短所
直感に基づいて今最適化する生産的に感じる。ときどきの幸運な勝利たいてい誤ったコードを調整する。利益なしに複雑さを加える
まず測定し、それから最適化する本物のボトルネックを狙う。証拠に基づくツールと規律が必要。始まりが遅い
キャッシュ大きなレイテンシとスループットの利得無効化のバグ。古いデータ。メモリのコスト
より多くの並列性並列な仕事でのより高いスループットアムダールの上限。競合。並行性のバグ
マイクロ最適化定数倍を絞り出す天井が低い。可読性を損なう。しばしば雑音
アルゴリズムの改善入力サイズとともに勝利が伸びる分析が必要。ときにより大きな書き直し
CIの性能ゲート回帰を早く安く止める不安定なベンチマークは信頼を蝕む。安定した環境が必要

中心的な緊張は労力と見返りであり、解決は測定です。性能の仕事には収穫逓減が鋭くあります。最初のプロファイルに導かれた修正はレイテンシを半分にするかもしれませんが、10番目はコードの複雑さを倍にしながら1パーセントを削るだけかもしれません。手元に数字と達成すべき予算がなければ最適化しないと拒むことで解決します。測定して、行う価値のある修正を見つけ、速度そのものを追うのではなく、予算を超えた瞬間に止めてください。

チームで議論すべき問い

  1. 重要な経路に、書面の性能予算はありますか。そしてそれはパーセンタイルで表現されていますか。 多くのチームは、ものが「速い」べきだという漠然とした感覚を持ちながら、誰も不合格にできる数字を持たず、それは、壊れるまで性能が誰の仕事でもないことを意味します。「p99が300ミリ秒未満」のような予算は、目標を具体的にし、レビュアーに徹底するものを与え、回帰をゆっくりした滑落ではなく目に見えるイベントに変えます。レイテンシが多くの手を通じて忍び込み、誰か一人の作者が累積のコストを見ない大きなチームで、最も重要になります。現在のレイテンシのデータを持ち込み、あなたを持ち上げる平均を報告しているのか、真実を語るパーセンタイルを報告しているのかを問ってください。「十分速い」が何を意味するかを数字で言えないなら、それが最初に直すことです。

  2. 最後に何かを最適化したとき、プロファイラがどこを見るべきかを教えましたか。それとも推測しましたか。 ボトルネックは、経験豊富なエンジニアが予想する所とは別の場所にあることで有名で、誤ったコードの調整に費やされた時間は二重に失われます。仕事そのものと、加えられた複雑さで。最初にプロファイルする文化は、労力を見返りのある所に使い、明快なコードをそのままにします。チームに、直近の三つの性能の修正を思い出してもらい、それぞれが測定から始まったか、勘から始まったかを尋ねてください。本番、あるいは現実的なステージング環境でプロファイルできるか検討してください。ノートPCのプロファイルはひどく誤解させうるからです。答えは、性能の仕事がエンジニアリングなのか民間伝承なのかを明らかにします。

  3. 今日、性能の回帰が本番に届くのを止めているものは何ですか。 成長するチームでは、正直な答えはしばしば「顧客の不満」であり、それはユーザーが回帰テストであることを意味します。ベンチマークや予算が悪化したらビルドを失敗させるCIゲートは、修正が安く、作者がまだ変更を覚えているうちに問題を捉えます。ベンチマークがゲートにできるほど安定しているか議論してください。オオカミ少年のように騒ぐ不安定な性能テストは、無視されるか無効にされるからです。本番で何を見ているかも話し合ってください。一部の回帰は、本物のトラフィックとデータのもとでしか現れないからです。目標は、性能を、インシデントで再発見するものではなく、システムが自動的に守る特性にすることです。

  4. 重要な経路ごとに、レイテンシとスループットのどちらを最適化していて、誰かがその選択を書き留めましたか。 これらは反対方向に引き合う別の目標です。バッチ処理と並列ワーカーはスループットを引き上げますが、個々のリクエストにレイテンシを加えうるので、直感で最適化するチームはしばしば誤った軸を買い、誰も不足していなかったマシン時間を節約するためにユーザーを待たせます。大きなチームでは危険が増幅します。あるグループが共有のサービスを一括のスループットのために調整する一方、別のグループが対話的なレイテンシのためにそれに依存し、どちらも相手の目標を知らないからです。各経路の実際の使用パターン(対話的なリクエストかバックグラウンドのバッチか)、現在のパーセンタイルのレイテンシ、必要な持続的なスループットを持ち込み、既定が現れるに任せるのではなく、軸を明示的に決めてください。SLAのもとにある企業や政府のシステムでは、合意がどの指標に対して書かれているかを名指ししてください。測定されない軸を最適化すると、ダッシュボードは健全に見えながら契約に違反しうるからです。

  5. ベンチマークが、オプティマイザがテストを削除したのではなく、本物の仕事を測っていることをどう知りますか。 嘘をつくベンチマークは、チームに偽りの確信を与え、それでも回帰が出荷されるので、ないよりも悪いものです。チームは日常的に、おもちゃの入力でのコールドランからの一回の幸運な数字を報告し、それはユーザーが実際に当たる振る舞いではなく、起動、ジャストインタイムコンパイル、使われないコードを取り除くコンパイラの能力を測っています。ベンチマークの例を持ち込んで問いただしてください。ウォームアップするか、多くの反復を実行するか、分散を報告するか、代表的なデータサイズと分布を使うか、結果のデッドコード削除を防いでいるか。相反する引力は、正直なベンチマークは書くのも実行するのも、手早いマイクロベンチマークより遅いことなので、安価な近似がどこで許容され、どこで厳密さを求めるかに合意してください。調達や監督機関が数字の再現を求める公共や規制された設定では、主張が単に断言されるのではなく検証できるよう、結果とともにデバイス、ワークロード、環境を記録してください。

  6. 性能の仕事が同じエンジニアを求めて機能と競合するとき、どう決め、予算の権限は誰が持ちますか。 性能には鋭い収穫逓減があり、最初のプロファイルに導かれた修正がレイテンシを半分にしても、10番目は倍のコードの複雑さで1パーセントを削るだけかもしれず、ルールがなければ、最も声の大きい人や最も近い締め切りが勝ちます。相反する考慮は本物です。直されない性能負債は静かに複利で増え、後付けするほど高価になりますが、予算を超えて速度を追うと、ロードマップを飢えさせ、将来の仕事を遅くする複雑さを加えます。重要な経路ごとの現在の予算の状況、現状維持のマシンや失われたコンバージョンでの推定コスト、次の最適化の限界的な見返りを持ち込み、トレードオフが圧力ではなく証拠でなされるようにしてください。大きな企業や政府のプログラムでは、性能予算を誰が所有し、それに対してエンジニアリングの時間を使うことを誰が承認できるかを名指ししてください。誰も守る責任を負わない目標は、静かに浸食されるものだからです。

セクター別の視点

スタートアップ。 デリバリーの速度がプロセスに勝るので、書き直しや壮大な性能フレームワークに抵抗してください。ユーザーが実際に不満を言う経路にプロファイラを使って午後を一つ費やし、最大のコスト(しばしばN+1クエリや偶然の線形スキャン)を直し、勝利が静かに回帰しないよう、軽いパーセンタイル予算をCIに一つ加えます。深い最適化は、勘ではなく本物の数字が、コードが遅すぎると言う瞬間のために取っておきます。

小規模事業者。 性能の専門家はおらず予算も厳しいので、すでに払っているツールに頼ってください。ランタイムのプロファイラ、ホスティングのダッシュボードのレイテンシのパーセンタイル、データベースに組み込まれたクエリアナライザー。ページの読み込みやチェックアウトの時間のような、顧客が感じるものに結びついた、単純な予算を一つか二つ設定し、違反を、人員を配置できないチューニングのプロジェクトを始めるのではなく、より速い階層を買うか、最悪のクエリを直すシグナルとして扱います。

大企業。 フリートの規模では、性能は直接のコストなので、共有の規律として統治します。標準のプロファイリングツール、ビジネス指標に結びついたパーセンタイル予算、そしてどの単一のチームのじわじわした劣化もクラウド全体の請求を膨らませないよう、一貫して適用されるCIの回帰ゲート。サービス間でレイテンシ、アロケーション、スループットをベースラインに対して追跡し、再現可能なベンチマークの証拠を保ちます。大きなフリートでのCPU 30%の削減は、監査して、SLAのペナルティに対して擁護する価値のある、繰り返し発生する節約だからです。

政府。 性能はアクセスの保証です。弱い接続の古い電話で読み込めるページが、市民が給付の申請を完了するかどうかを決めます。現実的な低価格帯のデバイスと絞られたネットワークに対する明示的な予算を設定し、調達や監督機関が数字を信用に頼らず検証できるよう、デバイス、ネットワーク、ワークロードを記録した再現可能なベンチマークの結果を公開します。ベンダーの主張より、透明で監査可能な測定を好み、供給者にも同じ再現可能な証拠を求めます。

事例

スタートアップ。 小さなSaaSチームは、ダッシュボードが重く感じられることに気づき、より速いフレームワークでの書き直しに誘われます。代わりに、プロファイラとフレームグラフで午後を費やし、リクエスト時間の70%が、行ごとに一つのデータベースクエリを発行する単一のエンドポイントであること、古典的なN+1のパターンだとわかります。それを一つのバッチクエリに置き換え、レイテンシは1.2秒から90ミリ秒に下がり、修正が静かに回帰しないよう、軽いCIベンチマークに200ミリ秒のp99予算を加えます。書き直しなし、午後一つ、十倍の勝利。

大企業。 小売プラットフォームは何千ものインスタンスを運用していて、クラウドの請求は一つの推薦サービスが支配しています。プロファイリングのキャンペーンで、頻繁なガベージコレクションの停止を引き起こす激しいアロケーションの変動と、ヒット率の悪いキャッシュが見つかります。局所性のためのデータ構造の調整とキャッシュキーの修正で、リクエストあたりのCPUが40%減り、同じトラフィックを40%少ないマシンで動かせるようになります。その節約は数週間でエンジニアリングの労力の元を取り、ときどき違反していたp99レイテンシのSLAは、今や余裕をもって守られ、契約上のペナルティを避けられます。

政府。 国の税務当局は、古いデバイスと遅い地方の接続の市民に仕えなければなりません。チームは明示的な予算を設定します。申告のページは、低価格帯の電話で、絞られた3Gのプロファイルのもとで、3秒未満で対話可能にならなければなりません。ページをプロファイルし、対話をブロックする処理を削り、デバイス、ネットワーク、ワークロードを記録した再現可能なベンチマークの結果を公開して、監督機関とアクセシビリティの監査人が、主張を信用に頼らず検証できるようにします。ここでの性能は、コストのてこではなく、サービスを全員が使える状態に保つアクセスの保証です。

ビジネスケース: 動機、ROI、TCO

パフォーマンスエンジニアリングの見返りは、三つの帳簿に現れます。一つ目はインフラのコストです。速いコードは同じ仕事をより少ないマシンでこなし、大きなフリートでは、CPU 30%の削減は、一度きりのエンジニアリングの労力をはるかに上回る、直接の繰り返し発生する節約です。二つ目は収益と満足です。レイテンシはコンバージョン、離脱、ユーザーの信頼と相関するので、裾を削ることは、単なる衛生の作業ではなく、成長のてこです。三つ目は避けられたリスクです。SLAの違反はペナルティを伴い、負荷のもとで溶けるローンチは、評判の傷と消火活動のコストを伴います。

総所有コストはささやかで、前倒しです。プロファイリングのツール、安定したベンチマーク環境、CIのゲートと、予算を書きプロファイルを読む規律に投資します。より大きく隠れたコストは、その代替です。性能の負債は静かに複利で増え、ローンチ後に遅いシステムへ速度を後付けすることは、継続的に守るよりはるかに高価です。リーダーシップにはその言葉で論拠を示してください。レイテンシをコンバージョンや市民の完了率に翻訳し、CPUを月々のクラウド支出に翻訳し、回帰ゲートを避けられたインシデントに翻訳します。最も強い論拠は、性能はコミットごとに守るなら安く、腐ってから回復するなら破滅的に高いということです。

アンチパターンと落とし穴

  • プロファイルせずに最適化する。 本物のコストが手つかずのまま、ボトルネックでないコードを調整すること。
  • 早すぎる最適化。 プロファイラが決して指摘しなかったであろう想像上の速度のために、明快さを犠牲にすること。
  • 平均の報告。 心地よい平均の陰に苦痛な裾を隠すこと。ユーザーが感じるのは平均ではなくp99です。
  • マイクロベンチマークの芝居。 ウォームアップも分散の報告もない、オプティマイザが半ば削除したおもちゃのワークロードからの数字。
  • 無効化の筋書きのないキャッシュ。 古いデータや間違ったデータを返しながらヒット率を追うこと。
  • スレッドを増やせば役立つと想定する。 アムダールの法則と直列の割合を無視し、競合に溺れること。
  • 回帰ゲートがない。 CIに予算を守るものが何もないため、ユーザーに性能テストをさせること。
  • 誤った軸の最適化。 ユーザーが低レイテンシを必要としたのにバッチ処理でスループットを買う、あるいはその逆。

成熟度モデル

  • レベル1、開始: 性能は何かが壊れたときにだけ対処されます。予算も、プロファイリングの習慣も、ベンチマークもなく、最適化は直感に駆られた当て推量で、平均が誰もが報告する唯一の指標です。
  • レベル2、発展: 一部のチームはインシデント中にプロファイルし、いくつかのベンチマークを保ちますが、実践は一貫せず、個人の熱意に依存します。予算は一つか二つの重要な経路について非公式に存在し、パーセンタイルは一部のダッシュボードに現れますが、出荷前に回帰をゲートするものはなく、各チームが独自のアプローチを再発明しています。
  • レベル3、標準化: 重要な経路は書面のパーセンタイル予算を持ち、プロファイリングは誰かが最適化する前の、文書化された期待される最初のステップです。CIは回帰ゲート付きの性能テストを含み、正直なベンチマークのルール(ウォームアップ、分散、代表的なデータ)は書き留められて組織全体で徹底され、すべてのチームが独自のものではなく同じ方法に従います。
  • レベル4、管理: 組織は性能を制御される特性として測定します。レイテンシのパーセンタイル、スループット、アロケーション率、遅いクエリの数が、本番とCIで明示的なベースラインに対して追跡され、回帰は議論されるのではなく閾値に照らして定量化され、予算はコンバージョンやクラウド支出のようなビジネス指標に結びつけられるので、違反はデータに裏付けられた決定を引き起こします。ベンチマークの証拠は再現可能で、監査のためにデバイス、ワークロード、環境とともに記録されます。
  • レベル5、オーケストレーション: 性能は継続的に改善され、組織全体に統合されています。予算、プロファイリング、正直なベンチマーク、フレームグラフの分析は日常のスキルで、回帰ゲートは安定して信頼され、本番とCIのデータがループを自動的に閉じます。組織はトラフィック、ハードウェア、ビジネスの優先事項の変化に応じて予算を調整し、労力を見返りが最も高い経路に再均衡させ、性能を、定期的なキャンペーンではなく常設の特性として守ります。

議論のためのアイデア

  1. 重要な経路のうち、今日書面のパーセンタイルに基づく予算を持つものはどれで、希望だけで守られているものはどれですか。
  2. 最後にプロファイラがあなたを驚かせたのはいつで、時間がどこに行くと想定しているかについて、それは何を教えましたか。
  3. ベンチマークはウォームアップし、分散を報告し、代表的なデータを使っていますか。それとも、オプティマイザを測っていますか。
  4. プロファイリングのキャンペーンならより安くできるコードを、マシンを費やして覆い隠しているのはどこですか。
  5. 最も並列化されたワークロードの直列の割合はどれくらいで、アムダールの法則は、追っている高速化に上限を課しますか。
  6. チームメイトがp99レイテンシを倍にする変更をマージしたら、誰かが気づくまでどれくらいかかり、どうやって知りますか。

要点

  • 最適化する前に測定します。ボトルネックは推測した所にはまずなく、早すぎる最適化は利益なしに明快さを犠牲にします。
  • 「十分速い」をパーセンタイルの予算として定義します。平均は、本物のユーザーがいる裾を隠すからです。
  • マイクロ最適化よりアルゴリズムの勝利(より良いビッグオーのクラス)を好み、レイテンシとスループットのどちらが必要かを知ります。
  • 並列性の限界(アムダールの法則)とキャッシュの危険(無効化と古さ)を尊重します。
  • ウォームアップ、分散、代表的なワークロードで正直にベンチマークし、マイクロベンチマークを疑います。
  • 性能をCI(2.4章)でゲートし、本番(9.2章)で観察します。3.5章のシステムレベルの見方を補完します。
  • 性能は、企業にとってはコスト、政府にとってはアクセスであり、継続的に守るなら安く、後付けするなら高くつきます。

参考文献とさらなる読み物

  • Brendan Gregg, Systems Performance: Enterprise and the Cloud (profiling, flame graphs, and method).
  • Brendan Gregg, BPF Performance Tools (practical observability and profiling on Linux).
  • Donald E. Knuth, “Structured Programming with go to Statements” (ACM Computing Surveys, 1974): the source of the premature-optimisation maxim.
  • Donald E. Knuth, The Art of Computer Programming (algorithmic analysis and complexity).
  • Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, Introduction to Algorithms (Big O and algorithmic efficiency).
  • Gene M. Amdahl, “Validity of the Single Processor Approach to Achieving Large-Scale Computing Capabilities” (1967): the origin of Amdahl’s law.
  • Ulrich Drepper, “What Every Programmer Should Know About Memory” (the memory hierarchy and data locality).
  • Martin Kleppmann, Designing Data-Intensive Applications (latency, throughput, and tail behaviour in systems).
  • Aleksey Shipilev, “JMH and the pitfalls of microbenchmarking” (honest benchmarking practice on managed runtimes).
  • Ilya Grigorik, High Performance Browser Networking (client-side and network performance for low-bandwidth users).