「推測するな、計測せよ」という訳はミスリードと言う話

パフォーマンス改善の文脈で良く用いられるフレーズとして、「推測するな、計測せよ」というものがある。これはRob PikeのNotes on Programming in Cからの引用なのだが、原典と少し印象が違う。

Rule 1. You can’t tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don’t try to second guess and put in a speed hack until you’ve proven that’s where the bottleneck is.

Rule 2. Measure. Don’t tune for speed until you’ve measured, and even then don’t unless one part of the code overwhelms the rest.

訳出する(正直あまり自信がない)と

Rule 1. プログラムが何処で処理時間を費やすのかは分からない。ボトルネックは驚くべき場所で起こる。だからその箇所がボトルネックであるという証明をするまで、当てずっぽう*1で高速化のためのハックを入れようとしてはならない*2

Rule 2. 計測せよ。計測するまで最適化*3をするな。そしてたとえ計測したとしても、ある部分のコードが圧倒的に残りの部分より重い場合でなければ、最適化をしてはならない。

つまりRob Pikeが批判しているのは「合理的な根拠なしに決めつけてハックをすること」であって、「推測」すること自体ではない。

むしろ私は「適切な推測」こそがパフォーマンス改善の肝であると言いたい。

 

そもそも、「適切な計測」は「適切な推測」なしに成り立たせるのが難しい。ある程度ボトルネックを推測し実験(計測)を繰り返しながら仮説を少しずつ強化し、改善策を入れるという作業が実際のパフォーマンス改善のワークロードに近い。

スクリーニングテスト的に一通りツールを試す価値は認めるが(詳解システムパフォーマンスのBrendan Greggの言うUSEメソッドなど)、推測なしに計測したところで一見問題ないように見えてしまうことがある。例えば代表値として平均を用いている場合bimodalやtail latencyは見えない。

他にもベンチマークツールやワークロードについての理解を得ずに計測した場合、計測した値が自分の意図したものとは異なっていることがある。例えばストレージの速度を計測しようとして実際にはページキャッシュ(つまりメモリ)の速度を計測しているといった状況はよくある。

Brendan Greggは計測こそベテランがやれと語っている。

 

また、ボトルネックの原因を理論的に「証明」することは現代の複雑すぎる計算機では実質的に不可能に近い(もしくは非常に煩雑である)場合がある。多くの自然科学が実験によってブラックボックスを解きほぐしていくように、推測を行ってはそれを棄却ないし強化するために実験を繰り返し、最終的にある仮定が正しいと信じられるだけだ。「証明」するというより、推測を積み上げた先に「限りなく正しいと思われる推測」が作られる。

Optimized C++でKurt Guntherothが言うように、必ずしもソフトウェアエンジニアは「証明」に取り組む必要はない。結局のところ、パフォーマンスが十分に改善されてしまえばそれでよく、「証明」自体は労力に対して得られるものが少ないことがあるからだ。必ずしもボトルネックの仮説を十分に強化してから改善に取り組まなければならないわけでもない。ある程度の整合性のある仮説があり、その仮説に則った改善策によって十分改善されるのであれば、その改善自体が仮説を強化出来る。

 

Brendan Greggはパフォーマンスの改善を医者の仕事に喩えているが、私はこのアナロジーが好きだ。医療の世界に擬えると、健康診断はスクリーニングテスト的だし、サットンの法則のような警句は良い指針になる。医者と違って我々は気軽に実験してマシンをリブートすることが出来る、なんと素晴らしいことか。病理医の仕事を描いた漫画の「フラジャイル」はパフォーマンス改善に取り組んでいる時に読むと刺さりまくったのでおすすめしたい。

 

8/28 追記

「そんなミスリードされるやつはおらん」と言う反応が思いの外多くて驚いた。その中には「推測するな、計測せよ」と言う訳/短縮は良くないという主張ではなくて、Rob Pikeの原典自体がミスリードなものという主張として受け取っている人が散見されたのでタイトルを修正しておいた。

私の日本語の感覚だと「根拠なしにハックするな、計測せよ」という主張を「推測するな、計測せよ」と訳すのはなかなか意味が変わっていると思う。実際のところは仮説検証のサイクルが肝要で、これは仮説を立てることが先んじてその検証は計測でなくても良いにも関わらず、measureがguessより大切に見えてしてしまう。

「推測」を「憶測」に変えれば良いとか、「推測だけするな」に変えれば良いだとかはまぁ今よりはマシだと思う。けどこういった短い言葉の捉え方の議論は紛糾しそうなので意図的に避けた。

結局短縮された格言は字面の意味が変わっていることがあるので原典を参照しようねというだけの教訓かも。

 

ベテランの人たちが「そんなことは当然だ」と主張するのはもっともで、あなたたち向けの記事ではないので安心して欲しい。こういった短縮された格言は初学者によく頼られる(また誤解される)ものなので。

 

そういった事件があったのかという指摘はギクっとして、何も仮定を立てずにそれっぽいツールが出してくるそれっぽい数値を参考にパフォーマンス最適化をして沼った経験がある。ベンチマークやワークロードをブラックボックスにしてしまうのって結構やってしまうと思っているんだけど、この正当化に「推測するな、計測せよ」が使われているシーンは何度も見た。つまり計測しているので正しいと主張してしまうケース。

心当たりが無い?本当に?

*1:guessは日本語の「推測」より「合理的な根拠のない推測」というニュアンス。second guessはより当てずっぽうというニュアンスのようだが、考え直すという意味で使われることもあってややこしい。

*2:Don't A until Bは「BするまでAするな」から転じて「Aをして初めてBをしろ」と訳出することが多いが、この文はそう訳出すると「ボトルネックがわかってから当てずっぽうでハックしろ」となってしまい意味が通らないので困る。もしかして原文もちょっとよろしくない?

*3:HackとTuneが対比されていそう。Hackはやっつけ、Tuneは最適化というニュアンス。