Wikipediaによると、プログラムの最適化の90/10ルールには、「プログラムの実行時間の90%がコードの10%の実行に費やされている」と記載されています(2番目のパラグラフ here を参照)。
私は本当にこれを理解していません。これはどういう意味ですか?実行時間の90%を、コードの10%だけを実行することに費やすにはどうすればよいですか?次に、コードの他の90%はどうですか?わずか10%の時間で実行できるのでしょうか。
ここには、2つの基本原則があります。
90/10ルールは文字通り真実ではありません。それはプログラムによって異なります(そして、私は特定の数90と10に根拠があるとは思えません。誰かがおそらくそれらを薄い空気から引き出したでしょう)。しかし、要点は次のとおりですプログラムをより高速に実行する必要がある場合、おそらくそれを実現するために重要なのは少数の行だけです。ソフトウェアの遅い部分を特定することは、最適化の最大の部分です。
これは重要な洞察であり、新しい開発者にとって直観に反するように見える決定は、多くの場合、正しい可能性があることを意味します。例えば:
これは自然の法則ではありませんが、幅広い経験から生まれた経験則です。これは80/20ルールとも呼ばれ、大まかな概算にすぎません。
ループ、ブランチ、その他のフロー制御
Ifがある各場所には、他のブランチよりも頻繁に使用される1つのブランチがあります。したがって、実行時間の多くは、プログラムの他の部分ではなく、その部分の実行に費やされます。
複数回実行されるループがある各場所には、周囲のコードよりも多く実行されるコードがあります。したがって、そこではより多くの時間が費やされます。
例として、次のことを考慮してください。
_def DoSomeWork():
for i in range(1000000):
DoWork(i)
except WorkExeption:
print("Oh No!")
_
ここで、print("Oh No!")
は最大で1回しか実行されず、多くの場合は実行されませんが、DoWork(i)
は約100万回発生します。
ループ。
そこに立ち寄りたくてたまらない! :-)
このプログラムを検討してください
1. do_something
2. loop 10 times
3. do_another_thing
4. loop 5 times
5. do_more_stuff
ライン1は1回実行され、ライン3は10回実行されます。各行を順番に見る
1 1 0.8%
2 10 8.3%
3 10 8.3%
4 50 41.3%
5 50 41.3%
2行が実行時間の83%を占めます(すべての行の実行にほぼ同じ時間がかかると仮定すると、プログラムの40%は80%以上かかります)。
より大きな実世界の例では、これが上昇するため、実行時間の大部分を占めるのはほんのわずかな行だけです。
90/10ルール(または80/20と呼ばれることもあります)は「経験則」であり、ほぼ真実です。
パレート原理も参照
実行時間のみについて質問したので、次の例が役立つ場合があります。
_int main() {
sleep(90); // approximately 10% of the program.
// other 90% of the program:
sleep(1);
sleep(1);
sleep(1);
sleep(1);
sleep(1);
sleep(1);
sleep(1);
sleep(1);
sleep(1);
sleep(1);
return 0;
}
_
もう少し深刻な場合は、実際のコードでは、ほとんどの場合(sleep(90);
の代わりに)ループ内で重い関数を呼び出し、残りの10%の時間は単一の計算を渡します。
別の例は、一部のHAサービスでのエラー処理です。高可用性サービスは、正常に動作するように設計されています無限通常の状態での時間。通常は99%の時間で動作しますが、エラーが発生した場合は、サービス自体よりも論理的に複雑なエラー処理と回復が実行されることがあります。
90/10の推論は、コードのごく一部が繰り返されるか、他のコードよりも多く使用されることを意味します。これは、開発/最適化作業の90%をこのコードの10%に集中させる必要があることを示唆するためによく使用されます。
Microsoft Word または OpenOffice のような通常のテキストプロセッサを考えてみます。
このことわざは経営科学でも使われています...これは人生そのものへの教訓です...意味:より多くの結果が得られるところに努力のほとんどを集中させます。
次のようなプログラムを想像してみてください。
print "H"
print "e"
print "l"
print "l"
print "o"
for i=0 to 1,000,000
print "How long now?"
next
print "B"
print "y"
print "e"
ここに11行あり、11行のうち3行がforループで、このかなり小さなコードにどれだけの時間が費やされているかに注意してください。他の8行は単に1文字を印刷しているだけですが、かなり少しです。したがって、一部のコードは短いかもしれませんが、それがどれだけ頻繁に実行され、どれだけの時間がかかるかを教えてくれないことに注意してください。
これは、「多くのイベントで、効果の約80%が原因の20%からもたらされる」と述べている「パレートの原則」の再解釈であり、80/20ルールとしても知られています。このルールは主に経済学に適用されるため、プログラミングのために再利用されるのは理にかなっています。
それは長い間観察されてきたパターンにすぎません。
これは、このようなパターンに関する非常に素晴らしいビデオであり、パレートの原理についても説明しています。
https://www.youtube.com/watch?v=fCn8zs912OE&ab_channel=Vsauce
それはルールではありません、それはウィキペディアを編集して、いくつかの数字を薄い空気から引き出し、それをルールと呼んだ、ただの男です。他のコンテキストでよりしっかりと確立されているパレート原理と比較してください。この「ルール」の正確性についてどのような調査が行われたか(もしあれば)を見たいのですが。
しかし、基本的にはあなたの質問に対する答えは、いくつかのコードは他のコードよりもはるかに頻繁に実行されるということです。ループが原因であることがよくあります。その他の理由は、時間のかかる呼び出しです。 Webサービスやストレージメディアなどの外部リソースへ。
ループに加えて、他のすばらしい回答で述べられているように、DRY考慮すべき原則もあります。よく書かれたオブジェクト指向コードには、再利用可能な部分がたくさんあります。定義により、再利用される部分は、一度だけ実行されるものの少なくとも2倍の頻度で使用します。OOコードがたくさんある場合、いくつかのクラスとメソッドを何度も再利用している可能性があります。コードは1回だけです。
他の回答で述べたように、1回しか使用されないコードを改善するよりも、頻繁に使用されるコードを改善する努力を費やす方が良いでしょう。