多くの場合、開発者は、問題を解決するための2つの可能な方法から選択することに直面します。1つは慣用的で読みやすい方法で、もう1つは直感的ではないがパフォーマンスが向上する可能性があります。たとえば、Cベースの言語では、数値に2を掛ける方法は2つあります。
int SimpleMultiplyBy2(int x)
{
return x * 2;
}
そして
int FastMultiplyBy2(int x)
{
return x << 1;
}
最初のバージョンは、テクニカルリーダーと非テクニカルリーダーの両方で簡単に選択できますが、ビットシフトは乗算よりも簡単な操作であるため、2番目のバージョンの方がパフォーマンスが向上する可能性があります。 (今のところ、コンパイラのオプティマイザがこれを検出して最適化しないと仮定しましょう。ただし、これも考慮事項です)。
開発者として、最初の試みとしてどちらが良いでしょうか?
あなたは1つを逃した。
正確さのために最初のコード、次に明確にするために(もちろん、2つはしばしば接続されています!)。最後に、実際に必要な実際の経験的証拠がある場合にのみ、最適化を検討できます。時期尚早の最適化は本当に悪です。ほとんどの場合、最適化には時間、明快さ、保守性が必要です。それで価値のあるものを購入していることを確認したほうがいいでしょう。
優れたアルゴリズムは、ほとんどの場合、ローカライズされたチューニングよりも優れていることに注意してください。正しく、明確で、高速なコードを入手できない理由はありません。しかし、「速い」ことに焦点を合わせてそこに着くのは不当に幸運です。
パフォーマンスが測定され、より高速なバージョンが必要になるまで、IMOは最初に明らかに読み取り可能なバージョンです。
Don Knuth からそれを取る
時期尚早の最適化は、プログラミングにおけるすべての悪(または少なくともそのほとんど)の根源です。
読みやすさ100%
コンパイラが "x * 2" => "x << 1"の最適化を実行できない場合は、新しいコンパイラを入手してください。
また、プログラムの時間の99.9%は、ユーザー入力の待機、データベースクエリの待機、およびネットワーク応答の待機に費やされていることを忘れないでください。 20億回の倍数を実行しない限り、それは目立たないでしょう。
読みやすさ。
パフォーマンスのコーディングには、独自の課題があります。ジョセフ・M・ニューカマーはそれを言った よく
最適化は、重要な場合にのみ重要です。それが重要であるとき、それは非常に重要ですが、それが重要であることがわかるまで、それをするのに多くの時間を無駄にしないでください。それが重要であると知っていても、それがどこで重要であるかを知る必要があります。パフォーマンスデータがないと、何を最適化するかわからず、おそらく間違ったものを最適化することになります。
結果はあいまいで、書きにくく、デバッグしにくく、問題を解決しないコードを維持するのが難しくなります。したがって、(a)ソフトウェア開発とソフトウェア保守のコストが増加すること、および(b)パフォーマンスへの影響がまったくないことの2つの欠点があります。
あなたの与えられた例では、そこにあるコンパイラの99.9999%が両方の場合に同じコードを生成します。これは私の一般的なルールを示しています-最初に読みやすさと保守性のために書き、必要なときにだけ最適化してください。
確かに読みやすさ。誰かが文句を言わない限り、速度について心配しないでください
読みやすさ。最適化する時期は、ベータテストを開始するときです。そうでなければ、あなたはあなたが時間を費やす必要があるものを本当に知ることは決してありません。
私は読みやすさ最初に行きます。最近のような最適化された言語と大量にロードされたマシンを使用すると、読みやすい方法で記述したコードのほとんどが適切に実行されます。
いくつかの非常にまれなシナリオでは、パフォーマンスのボトルネックが発生することがかなり確実であり(過去の悪い経験からのものである可能性があります)、パフォーマンスを大幅に向上させることができる奇妙なトリックを見つけることができました。それ。ただし、そのコードスニペットには非常によくコメントする必要があります。これにより、コードスニペットが読みやすくなります。
この議論で見過ごされがちな要因は、プログラマーが読みにくいコードをナビゲート、理解、変更するのに余分な時間がかかることです。プログラマーの時間が1時間に100ドル以上かかることを考えると、これは非常に現実的なコストです。
パフォーマンスの向上は、開発におけるこの直接的な追加コストによって相殺されます。
説明付きのコメントをそこに置くと、読みやすく高速になります。
それは本当にプロジェクトの種類とパフォーマンスの重要性に依存します。 3Dゲームを構築している場合、通常、途中でそこに投入したい一般的な最適化がたくさんあり、そうしない理由はありません(早めに夢中になりすぎないでください)。しかし、あなたがトリッキーなことをしているなら、それをコメントしてください。そうすれば、それを見ている人は誰でもあなたがトリッキーである方法と理由を知ることができます。
答えは状況によって異なります。たとえば、デバイスドライバーのプログラミングやゲーム開発では、2番目の形式が受け入れられるイディオムです。ビジネスアプリケーションでは、それほど多くはありません。
最善の策は、コード(または同様の成功アプリケーション)を調べて、他の開発者がどのようにそれを行っているかを確認することです。
両方とも。コードは両方のバランスを取る必要があります。読みやすさとパフォーマンス。どちらかを無視すると、プロジェクトのROIが台無しになります。これは、結局のところ、上司にとって重要なことです。
読みやすさが悪いと保守性が低下し、保守に費やされるリソースが増え、ROIが低下します。
パフォーマンスが悪いと、投資と顧客ベースが減少し、ROIが低下します。
<<を使用すると、マイクロ最適化が行われます。したがって、Hoareの(Knutsではない)ルール:
時期尚早の最適化 はすべての悪の根源です。
適用され、そもそもより読みやすいバージョンを使用する必要があります。
これは、IMHOが、拡張できない、またはうまく機能しないソフトウェアを設計するための言い訳として誤用されることが多いルールです。
コードの可読性が心配な場合は、コメントを追加して、何を、なぜこれを行っているのかを思い出してください。
コードベースが大きいほど、読みやすさが重要になります。いくつかの小さな機能を理解しようとすることはそれほど悪くはありません。 (特に、例のメソッド名が手がかりを与えてくれるので。)彼はついに彼の能力の複雑さの頂点を見て、それが彼だけのものであるため、コーディングをやめたばかりの孤独な天才によって書かれたいくつかの壮大なユーバーコードにはあまり良くありませんあなたのために書いた、そしてあなたはそれを決して理解しないでしょう。
ボトルネックがわからなければ、最適化しても意味がありません。コードのその部分がほとんど実行されないことを見つけるためだけに(通常はある程度の可読性を犠牲にして)関数を信じられないほど効率的にしたかもしれません。したがって、測定するものができるまでマイクロ最適化することはできません。そうすれば、読みやすさから始めたほうがよいでしょう。ただし、アーキテクチャ全体を設計するときは、速度と理解しやすさの両方に注意する必要があります。どちらも大きな影響を及ぼし、変更が難しい場合があるためです(コーディングスタイルと方法によって異なります)。
読みやすさが最初の目標です。
1970年代に、軍はソフトウェア開発の当時の「新しい」技術のいくつか(トップダウン設計、構造化プログラミング、チーフプログラマーチームなど)をテストして、これらのどれが統計的に有意な違いをもたらしたかを判断しました。
開発に統計的に有意な違いをもたらした唯一の手法は...
プログラムコードへの空白行の追加。
これらの事前構造化された事前オブジェクト指向コードの可読性の向上は、生産性を向上させたこれらの研究の唯一の手法でした。
==============
最適化は、プロジェクト全体が単体テストされ、計測の準備ができている場合にのみ対処する必要があります。コードを最適化する必要がある場所がわかりません。
1970年代後半のKerniganand Plaugerの画期的な本で、SOFTWARE TOOLS(1976)とSOFTWARE TOOLS IN Pascal(1981)は、トップダウン設計を使用して構造化プログラムを作成する方法を示しました。彼らはテキスト処理プログラムを作成しました:エディター、検索ツール、コードプリプロセッサー。
完成したテキストフォーマット機能がINSTRUMENTEDされたとき、彼らは処理時間のほとんどがテキストの入出力を実行する3つのルーチンに費やされていることを発見しました(元の本では、io関数は89%の時間かかりました。Pascal本では、これらの関数55%消費しました!)
彼らはこれらの3つのルーチンを最適化することができ、合理的で管理しやすい開発時間とコストでパフォーマンスの向上の結果を生み出しました。
ビットシフト対乗算はゲインを得る簡単な最適化なしの隣です。そして、指摘されているように、あなたのコンパイラはあなたのためにそれをするべきです。それ以外は、この命令が実行されるCPUと同様に、ゲインは無視できます。
一方、本格的な計算を実行する必要がある場合は、適切なデータ構造が必要になります。しかし、問題が複雑な場合は、それを見つけることが解決策の一部です。 例として、1000000のソートされていないオブジェクトの配列でID番号を検索することを検討してください。次に、バイナリツリーまたはハッシュマップの使用を再検討してください。
ただし、n << Cのような最適化は通常無視でき、いつでも変更するのは簡単です。コードを読みやすくすることはできません。
解決する必要のあるタスクによって異なります。通常、読みやすさの方が重要ですが、そもそもパフォーマンスについて考えると、まだいくつかのタスクがあります。また、最適化自体ではコードの十分な部分を最初から書き直す必要がある場合があるため、すべてが完全に機能した後、1日またはプロファイリングと最適化に費やすことはできません。しかし、それは今日では一般的ではありません。
読みやすさを第一に。しかし、読みやすさ以上のものは単純さです特にデータ構造の観点から。
なぜこんなに遅いのか理解できなかった、視覚分析プログラムをやっている学生を思い出しました。彼は単に良いプログラミング慣行に従っただけです-各ピクセルはオブジェクトであり、それはその隣人にメッセージを送ることによって機能しました...
これをチェックしてください
読みやすさがなければ、本当に必要なときにパフォーマンスを向上させるのは非常に困難です。
パフォーマンスは、プログラムに問題がある場合にのみ改善する必要があります。この構文ではなく、ボトルネックになる場所がたくさんあります。 <<で1nsの改善を押しつぶしているが、10分IO時間であることを無視したとします。
また、読みやすさに関しては、プロのプログラマーがコンピューターサイエンスの用語を読んだり理解したりできる必要があります。たとえば、putThisJobInWorkQueueと言う必要はなく、メソッドにenqueueという名前を付けることができます。
常に最大限に最適化する必要があり、パフォーマンスは常に重要です。 今日私たちがブロートウェアを持っている理由は、ほとんどのプログラマーが最適化の仕事をしたくないからです。
そうは言っても、巧妙なコーディングで明確にする必要がある場所にはいつでもコメントを入れることができます。
私はグーグルで働いていないので、私は邪悪なオプションを選びます。 (最適化)
Jon Bentleyの「ProgrammingPearls」の第6章では、6つの異なる設計レベルで最適化することにより、1つのシステムが400倍高速化した方法について説明しています。これらの6つの設計レベルでのパフォーマンスを気にしないことで、最新の実装者はプログラムで2〜3桁の速度低下を簡単に達成できると思います。
ほとんどの人が答えで言ったように、私は読みやすさを好みます。私が実行している100のプロジェクトのうち99は、厳しい応答時間の要件がないため、簡単に選択できます。
コーディングを始める前に、すでに答えを知っている必要があります。一部のプロジェクトには、「タスクXをY(ミリ)秒で実行できる必要がある」などの特定のパフォーマンス要件があります。その場合は、取り組む目標があり、最適化する必要があるかどうかがわかります。 (うまくいけば)これは、コードを書くときではなく、プロジェクトの要件段階で決定されます。
読みやすさと後で最適化する機能は、適切なソフトウェア設計の結果です。ソフトウェアがサウンドデザインである場合、システムの他の部分を壊すことなく、ソフトウェアの一部を分離し、必要に応じてそれらを書き直すことができるはずです。その上、私が遭遇した最も真の最適化のケース(いくつかの実際の低レベルのトリックを無視して、それらは偶発的です)は、あるアルゴリズムから別のアルゴリズムに変更するか、ディスク/ネットワークではなくメモリにデータをキャッシュすることでした。
ソフトウェアのコストの約70%がメンテナンスに費やされていると推定されています。読みやすさにより、システムの保守が容易になるため、ソフトウェアの耐用年数にわたってコストが削減されます。
パフォーマンスが読みやすさよりも重要である場合があります。
読みやすさを犠牲にする前に、「私(またはあなたの会社)は、これを行うことによってシステムに追加する追加コストに対処する準備ができていますか?」と考えてください。
読みやすさ。それは他の人(または後日あなた自身)があなたが達成しようとしていることを決定することを可能にします。後でパフォーマンスについて心配する必要があることがわかった場合は、読みやすさがパフォーマンスの達成に役立ちます。
また、読みやすさに集中することで、実際には単純なコードになり、より複雑なコードよりもパフォーマンスが向上する可能性が高いと思います。
最初に読みやすさのために書いてください、しかし読者がプログラマーであることを期待してください。自分の塩に値するプログラマーは、乗算とビットシフトの違いを知っているか、適切に使用されている三項演算子を読み、複雑なアルゴリズムを調べて理解できる必要があります(コードにコメントしていますか? )など。
もちろん、初期の過剰最適化は、後でリファクタリングが必要になったときに問題が発生するのは非常に悪いことですが、個々のメソッド、コードブロック、またはステートメントの最適化には実際には当てはまりません。
「パフォーマンスは常に重要」は真実ではありません。 I/Oバウンドの場合、乗算速度は重要ではありません。
「今日私たちがブロートウェアを持っている理由は、ほとんどのプログラマーが最適化の仕事をしたくないからです」と誰かが言いました、そしてそれは確かに真実です。それらを処理するコンパイラがあります。
最近のコンパイラは、そのアーキテクチャに適している場合、x*2
をx<<1
に変換します。これは、コンパイラーがプログラマーよりもスマートである場合です。
私見両方のことは何の関係もありません。最初に機能するコードを探す必要があります。これは、パフォーマンスや読み取りの程度よりも重要だからです。読みやすさについて:どのような場合でも、コードは常に読みやすくする必要があります。
ただし、コードが読み取れず、同時に優れたパフォーマンスを提供できない理由がわかりません。あなたの例では、2番目のバージョンは最初のバージョンと同じくらい読みやすいです。それについて読みにくいものは何ですか?プログラマーが、左にシフトすることは2の累乗で乗算することと同じであり、右にシフトすることは2の累乗で除算することと同じであることを知らない場合...まあ、一般的な読みやすさよりもはるかに基本的な問題があります。
ほとんどの場合、読みやすさがはるかにより重要であるという世界のほとんどに同意します。コンピューターは想像以上に高速で、高速化するだけです。コンパイラーがマイクロ最適化を実行します。ボトルネックがどこにあるかがわかれば、後で最適化できます。
一方、場合によっては、たとえば、深刻な数値計算やその他の非対話型の計算集約型タスクを実行する小さなプログラムを作成している場合は、パフォーマンス目標を使用して高レベルの設計上の決定を行う必要があります。念頭に置いて。このような場合に後で遅い部分を最適化しようとすると、基本的にコードの大部分を書き直すことになります。たとえば、小さなクラスなどで物事をうまくカプセル化しようとすることはできますが、パフォーマンスの優先度が非常に高い場合は、たとえば、メモリ割り当ての数が少ない、因数分解の少ない設計を選択する必要があります。 。
私は読みやすさのために行くと思います。
しかし、与えられた例では、関数の名前が関数で何が起こっているかを正確に示しているので、2番目のバージョンはすでに十分に読み取り可能であると思います。
私たちがいつも私たちに教えてくれる関数を持っていたら、それらは何をしますか...
1時間のプロセッサ時間はどれくらいの費用がかかりますか?
プログラマーの1時間の時間はどれくらいかかりますか?
読みやすさを優先する必要があります。次に、メンテナが何かが標準ではない理由を理解できるようにコメントが付けられている場合は、パフォーマンスが向上します。