web-dev-qa-db-ja.com

コーディング時にマイクロ最適化は重要ですか?

[〜#〜] php [〜#〜]isset()がstrlen() よりも高速である理由を確認するために、最近Stack Overflowで質問しました。これにより、可読コードの重要性と、コード内のマイクロ秒単位のパフォーマンス改善が検討に値するかどうかという疑問が生じました。

私の父は引退したプログラマーで、私は彼に反応を示しました。彼は、コーダーがマイクロレベルでさえコードのパフォーマンスを考慮しない場合、彼らは優れたプログラマーではないと確信していました。

確かではありませんが、計算能力の向上により、この種のマイクロパフォーマンスの向上を考慮する必要がなくなります。多分この種の考慮は実際の言語コードを書く人々次第ですか? (PHP))。

環境要因は重要かもしれません-インターネットは世界のエネルギーの10%を消費します。何百万ものWebサイトで何兆回も複製されると、数マイクロ秒のコードがどれだけ無駄になるのでしょうか。

できればプログラミングに関する事実に基づいた答えを知りたいのですが。

コーディング時にマイクロ最適化は重要ですか?

すべてのおかげで私の25の回答の個人的な要約。

マイクロ最適化について本当に心配する必要がある場合もありますが、それは非常にまれな状況に限られます。ほとんどの場合、信頼性と可読性ははるかに重要です。ただし、時々マイクロ最適化を検討しても問題はありません。基本的な理解は、次のようなコーディングの際に明らかな悪い選択をしないようにするのに役立ちます

if (expensiveFunction() || counter < X)

する必要があります

if (counter < X || expensiveFunction())

@ zidarsk8からの例 )これは安価な関数である可能性があるため、コードの変更はマイクロ最適化になります。しかし、基本的に理解すれば、最初から正しく書くことができるので、その必要はありません。

181
Boz

私はあなたのお父さんに賛成と反対の両方をします。パフォーマンスは早い段階で考える必要がありますが、マイクロ最適化は早い段階で考える必要があります。実際には時間の高い割合が短い時間で費やされることを知っているコードのCPUバインドセクション。

マイクロ最適化の問題は、プログラムが実際に必要以上に多くの時間を費やす方法の概念がなくても実行できることです。

この知識は、パフォーマンスチューニングを行った経験から得られます この例のように 。ここでは、明らかな非効率性のない一見単純なプログラムが、43倍速くなるまで、一連の診断と高速化の手順を実行します。初めより。

それが示しているのは、問題がどこにあるのかを実際に推測したり直感したりできないことです。診断を実行すると、私の場合は ランダムな一時停止 であり、時間のかなりの部分を占めるコード行が優先的に公開されます。これらを見ると、代替コードが見つかる可能性があり、それによって全体の時間をおよそその分だけ短縮できます。

修正しなかった他の事柄は以前と同じくらいの時間がかかりますが、全体の時間が短縮されたため、これらの事柄はより大きな割合を占めるようになりました。もう一度やり直すと、その割合も排除できます。複数の反復にわたってこれを続けている場合、これは、必ずしも何もしなくても大規模高速化、を得る方法ですミクロ最適化

そのような経験の後、新しいプログラミング問題に取り組むとき、最初はそのような非効率性につながる設計アプローチを認識するようになります。私の経験では、データ構造の過剰設計、正規化されていないデータ構造、通知への大幅な依存などが原因です。

90
Mike Dunlavey

数値がそうであると言う場合にのみ、ミクロ最適化は重要です。

クライアントまたはユーザーにとってパフォーマンスがまったく問題となる場合、開発対象の要件には、パフォーマンスデータの仕様が含まれている必要があります。ソフトウェアを開発しているときに、これらの要件に対してシステムのパフォーマンスをテストする必要があります。パフォーマンス要件を満たしていない場合は、コードベースのプロファイルを作成し、必要に応じて最適化して、パフォーマンス要件を達成する必要があります。必要最低限​​のパフォーマンスの範囲内になったら、特にコードの可読性と保守性を損なう可能性がある場合は特に、システムからこれ以上のパフォーマンスを引き出す必要はありません(私の経験では、高度に最適化されたコードは読みにくく、保守可能ですが、常にではありません)。システムの他の品質属性を低下させることなく、パフォーマンスをさらに向上させることができる場合は、それを検討できます。

ただし、パフォーマンスが最も重要な場合もあります。私は主にリアルタイムシステムと組み込みシステムについて考えています。リアルタイムシステムでは、操作の順序を変更すると、適切な操作に必要なハードデッドラインへの対応に多大な影響を与える可能性があり、計算結果にも影響を与える可能性があります。組み込みシステムでは、通常、メモリ、CPU電力、および(バッテリー電力のように)電力が限られているため、システムの寿命を最大化するには、バイナリのサイズを小さくし、計算数を減らす必要があります。

120
Thomas Owens
  1. 簡潔、簡潔、簡単でわかりやすいコードを記述します。
  2. パフォーマンステストを行って、ボトルネックを特定します。
  3. 重要なセクションを最適化します。

経験則として、コードの95%が5%の時間実行されます。コードをプロファイル/ベンチマークして、95%の時間で実行される5%がどれかを確認する前に、最適化しても意味がありません。

すべてのばかはマイクロ最適化を行うことができ、まともなコンパイラ/ランタイムはこれをあなたのために行います。
適切なコードを最適化することは簡単です。最適化されたコードを記述してそれを改善しようとすることは、せいぜい退屈で、最悪の場合は持続不可能です。

真剣にパフォーマンスを重視する場合は、パフォーマンスが重要なコードにPHPを使用しないでください。ボトルネックを見つけて、C拡張機能で書き直してください。難読化のポイントを超えてPHPコードをマイクロ最適化しても、速度はほとんど変わりません。

個人的には、プログラミングを始めたとき、マイクロ最適化を非常に好きでした。それは明白だからです。それはあなたに素早く報酬を与えるからです。重要な決定をする必要がないからです。 完璧先延ばしの手段です。これにより、ソフトウェア開発の非常に重要な部分である、スケーラブルで柔軟性があり、拡張性があり、堅牢なシステムの設計から逃げることができます。

84
back2dos

私はあなたの父親に同意します。「コーダーがマイクロレベルでもコードのパフォーマンスを考慮しない場合、彼らは優れたプログラマーではありません。」鍵は「性能を考える」ことです。これは、「すべてのステップでマイクロ最適化を実行する」ことと同じではありません。

私は他のほとんどのコメントに同意します-Cプログラムを高速化するために使用されたものは今日はそうしないかもしれません-しかし、他に考慮すべき重要な点があります:CまたはC++を使用する必要がありますか?単純なオーバーロードされた演算子を持つクラスは、頻繁に使用するとパフォーマンスを低下させる可能性があります。それは重要ですか?それはあなたのアプリケーションに依存しますが、あなたがそれを考えさえしなければ、あなたは非常に優れたプログラマーではありません。一部の人々はそれを約2ミリ秒間考えてそれを却下するかもしれませんが、文字通りそれを考慮さえしない人が多すぎると思います。

実際には、最適化を行うとコードが読みにくくなる可能性があります。コードの記述には時間がかかります。コードは少し高速から1桁速くなります(これはまれです)。あなたの顧客はおそらく違いを知らないでしょう。

もう1つの現実は、人々がコードを再利用することを好み、最終的にどこでコードを書くかとはまったく異なる場合があることです。突然人々は気にするかもしれません。

例として、PC上またはゲームコンソール用に Angry Birds のようなものを書いたとします。物理システムとグラフィックスシステムの最適化を無視しました。2.5GHzデュアルコアが基本的に最近では最小であり、ゲームは十分に機能するためです。それからスマートフォンがやって来て、あなたはそれを移植したいと思っています。ああ、600 MHz [〜#〜] arm [〜#〜] コア?

Webサイトについて考えてみてください-Hot or Notのような週末に一緒に投げられるもの。使いやすいデータベースを使用し、迅速な開発を念頭に置いてすべてを記述し、友達にURLを電子メールで送信して起動します。 3か月後、サーバーが過負荷で死んでいて、スケールアップする方法がありません。それはいつも起こります。最大のWebサイトでは、電力料金が数百キロワットまたはメガワット単位で測定されています。考えてみてください。コードの最適化によって節約されるメガワットがあります。

あなたのお父さんが言ったように、あなたは少なくともそれを考えなければなりません。ほとんどの人は、テーブルのパフォーマンスがどれほどかわからないので、「時期尚早の最適化」と「やらない」という簡単なヒントでそれを理解します。これらは良いプログラマではありません。

これはこれらのサイトで人気のある意見ではありません。さようなら評判ポイント...

27
phkahler

最初にあなたのケースを取ってみましょう:PHP

  • PHPは、これらの「マイクロ最適化」について心配する必要がある種類の言語(その性質とアプリケーションのメインドメインのため)ではないと思います。PHPコードは主にopcodeキャッシングで最適化されています。
  • PHPで記述されたプログラムはCPUにバインドされていません。それらはほとんど I/O バインドされているため、これらの最適化はとにかく時間をかける価値はありません。
  • 最適化しなければならないものは、おそらくCの拡張機能に引き込んでから、PHPランタイムに動的にロードする必要があります。
  • ご覧のとおり、PHP-でコードをマイクロ最適化しても、PHP =より読みやすく、保守しやすいコード-これにより、より多くの配当が支払われます。

一般に、

PythonRuby -のような動的言語でコードを最適化するのに「TOOOOO」に多くの時間を費やしません。これらは、現実世界の状況を精巧な方法でモデル化する(読みやすく保守しやすい)問題のさまざまなクラスを解決します-これは と呼ばれます)表現力 -速度よりも重要です。速度が主な関心事である場合、そもそも動的ではありません。

コンパイルされたプログラム(C++、Java)の場合、最適化はより重要です。しかし、そこにも、まず、作成しているプログラムの性質/ドメイン/目的を確認する必要があります。また、マイクロ最適化にかかる時間と、その最適化による利益を慎重に比較検討する必要があります。さらに最適化が必要な場合は、一歩下がることを検討し、それらのコードをアセンブラーでコーディングすることもできます。

それで、あなたの元の質問に答えるために-「コーディング時にマイクロ最適化は重要ですか?」 -答えは-依存する-

  • アプリケーションドメイン、複雑さなど、どのようなことをしていますか?
  • マイクロ秒の速度の向上は、プログラムにとって本当に重要ですか?
  • どのような最適化が最も効果的ですか?それは常にコードの最適化ではないかもしれませんが、外部的なものです。
  • マイクロ最適化への投資に費やす時間から、どれほどの「スピード」を獲得できますか?
  • 他の方法でより良い速度を実現できますか?ハードウェア、RAM&プロセッサー、コードを並列実行、または分散システムで変更することによって?

マイクロ最適化(さらに言えばコードの最適化)は時間がかかるだけでなく、コードの自然な読みやすさを「歪め」、メンテナンスが重くなります。常に最後の手段と考えてください。常に、個々のコードファイルを最適化するよりも優れたハードウェアとアーキテクチャを採用して、アプリケーション全体を最適化するようにしてください。

25
treecoder

マイクロ最適化は

トレードオフに関するすべて-パフォーマンス、時間、コスト、労力、可読性/保守性など。

しかし、可読性に影響を与えない最適化がいくつかあることは承知しています。私はそれをただ楽しみたいだけです。私はいくつかの学校の割り当て(すべて速度ベース)を見て、次のような条件付きステートメントを記述するときは常にマイクロ最適化を検討するのがいいと思います。

if (counter < X && shouldDoThis()) // shouldDoThis() is an expensive function

常により良いです

if (shouldDoThis() && counter < X ) 

このようにコードを「高速化」するにはいくつかの方法があり、その違いは通常は無視できます(ただし、常にそうであるとは限りません)が、そのように記述すれば気分が良くなります。

これを実際の最適化と見なす人がいるかどうかはわかりませんが、プログラマーはコードを書くときにこれらのことを知って検討する必要があると思います。

18
zidarsk8

私のキャリアの初期には、「マイクロ最適化しないでください」などの包括的な声明が多くの混乱を招きました。すべては状況に依存します。したがって、人々が「これを行う」ではなく「ベストプラクティス」と言う理由。

「ベストプラクティス」は、すべての状況を考慮した場合の最優先事項です。たとえば、インラインSQLの代わりに [〜#〜] linq [〜#〜] および Entity Framework を使用する必要があります。私の会社では SQL Server 20 を使用しています。 SQL Server 2000はEntity Frameworkをサポートしていません。ベストプラクティスには次のものが必要です。

  • 数千ドルを意味するSQL Serverの新しいバージョンを購入するという考えで上司を売ります。
  • 新しいテクノロジーを学ぶというアイデアで開発者を販売する。

経験上、これは起こらないことを知っています。だから、やめたり、終わりのないストレスをしたり、ベストプラクティスに従わなかったりする可能性があります。

全体的な結果に影響を与える決定の背後には、政治的、技術的、金銭的な考慮事項があります。決定を下すときはこの事実を思い出し、賢明な戦いを選択してください。

すべての季節があり、天国でのあらゆる活動の時間です。

11
P.Brian.Mackey

これは常にトレードオフです。

第一に、コンピューター業界は結局のところお金です。開発者として行う必要があるのは、顧客に価値を生み出してお金を稼ぐことです(これは単純化しすぎですが、ここでの要点はここにあります)。

開発者の時間はお金がかかります。機械の動力にもお金がかかります。通常、この2番目のコストは最初のコストよりもはるかに低くなります。したがって、これは可読コードと保守可能なコードを持つための資本であり、開発者はほとんどの時間を価値の提供に費やすことができます。

マイクロ最適化は、場合によっては重要です。ただし、通常、読みにくいコードや拡張性の低いコードが含まれます(これは、リンクされた例の場合ではありませんが、一般的にはそうです)。これは、開発者のある時点でコストがかかります。今回は機械の動力よりも高価なので、これは無駄です。

第2に、大規模プロジェクトでのマイクロ最適化は、維持/進化をますます困難にする可能性があります。それに関する問題は、進化するとき、他のいくつかの最適化が今や不可能になるかもしれないということです。進化するアプリケーションでは、通常、これらの最適化を行わなかった場合よりも遅いソリューションになります。

第3に、アルゴリズムの複雑さは一般に、データセットが大きくなった場合に実行できたあらゆるマイクロ最適化を克服するため、最適化はしばしば影響を受けません。悲しいことに、マイクロ最適化によりコードの保守/進化が難しくなるため、これらの最適化は難しくなる可能性があります。

時々、価値はこの最適化にあります(ビデオゲームや航空機の自動操縦のような待ち時間が重要なプログラムについて考えてください)。しかし、これは実証されなければなりません。通常、プログラムはほとんどの時間をコードの限られた部分で費やします。どのようなミクロ最適化を行っても、ボトルネックを特定してこの部分に取り組むことなく、プログラムを大幅に高速化することはできません。

あなたがしたようにあなたの質問をすることはあなたが実際のプログラムで問題をベンチマークしなかったことを示しました。この場合、あなたはトリックを行うことができ、それがより速いかどうかに気づいたでしょう。それで、あなたは問題がある前にそれを尋ねていました。ここが問題です。あなたは最適化の問題を間違った方法で扱っていました。

通常、メンテナンスと進化はマイクロ最適化よりも価値があるので、何かを行う前に適切なインターフェースを持っていることを確認してください。次に、プログラムの一部が相互に十分に抽象的である場合、全体を台無しにせずに1つをマイクロ最適化できます。これには、インターフェイスが信頼できるほど長く実行されている必要があります。

8
deadalnix

パフォーマンスは機能です

Jeff Atwoodの記事は、高性能なWebサイトの構築に関するすばらしい記事であり、そうすることの重要性です...

とはいえ、必要になるまでマイクロ最適化に集中しないでください。実行できる費用対効果の高い最適化があります。コードではなく、アーキテクチャに焦点を当てます。動作が遅いことがわかっているほとんどのWebサイトには、パフォーマンスに悪影響を与えるだけでなく、根底にあり修正が困難な高レベルの問題(不要なWebサービスレイヤー、不十分なデータベース設計、過度に複雑なアーキテクチャ)がありました。

Webサイトを構築しているとき、クライアント側のコードとデータベースロジックは、サーバー側のコードよりもパフォーマンスの問題を引き起こす可能性がはるかに高くなります。ただし、他のことと同様に、パフォーマンスの問題がある場合は、コードをより適切にプロファイリングすれば、それらを早い段階で見つけることができます。

8
Mike Cellini

何を最適化しますか?

  • ソフトウェアのパフォーマンス?
  • 信頼性は?
  • プログラマの生産性?
  • 顧客満足?
  • 電力効率?
  • 保守性?
  • 市場投入までの時間?
  • 費用?

「最適化」は、常にコードを可能な限り高速に実行することを意味するわけではありません。何かを行うための絶対最速の方法を見つけることが重要な場合がありますが、それはほとんどのコードでそれほど一般的ではありません。ユーザーが50マイクロ秒と100マイクロ秒の違いに気付かない場合、たまにしか実行されないコードでは、2つの違いは事実上ありません。次に例を示します。

ユーザーの入力の長さと、2つのルーチンのいずれかが長さが2つの連続するキーストローク間の時間よりもはるかに短いと判断するのにかかる時間の表示を継続的に更新する必要がある場合、どのルーチンでも問題ありません。あなたが使う。一方、10億個の文字列の長さを判別する必要がある場合は、異なるルーチン間のパフォーマンスの違いに細心の注意を払う必要があるでしょう。最初のケースでは、理解と検証が簡単なコードを作成することをお勧めします。 2番目のケースでは、読みやすさと速度のトレードオフをいとわないかもしれません。

いずれにしても、コードを最適化する場合は、変更の前後にコードをプロファイルする必要があります。最近のプログラムは非常に複雑で、ボトルネックがどこにあるのか見分けるのが難しい場合があります。プロファイリングは正しいコードを最適化するのに役立ち、行った最適化が実際に機能したことを示します。

父親がいつ引退したか、どのようなプログラミングをしたかは言わなかったが、彼の反応は驚くに値しない。歴史的に、メモリ、二次ストレージ、および計算時間はすべて高価であり、時にはvery高価でした。最近では、これらすべてがプログラマの時間と比較してvery安くなっています。同時に、プロセッサーとコンパイラーは、プログラマーが決して一致できない方法でコードを最適化できるようになりました。プログラマーがここでいくつかの機械語命令を燃やすために少しのトリックを使用する時代は、ほとんどなくなっています。

7
Caleb

コードの記述中にマイクロ最適化を行うことは重要ではありません。最適化はプロファイラーの助けを借りて行う必要があり、重要な場所でコードを最適化します。

[〜#〜]ただし、[〜#〜]、プログラマーは、書き込み中に明らかに愚かなことをしないようにしてくださいコード。

たとえば、ループ内で負荷の高い操作を繰り返し実行しないでください。ループの外の変数に値を格納し、それを使用します。よく呼び出される関数では、文字列比較や正規表現などを何度も行わないでください。レベルを上げて比較を行い、整数または関数参照または派生クラスにすることができます。

これらのことは、経験豊富なプログラマにとって覚えやすく、ほとんど常にコードの品質を向上させます。

7
Zan Lynx

開発者の時間は、コンピュータの時間よりもコストがかかります。それは通常あなたが最適化したいものです。 しかし:

  • マイクロ最適化とアルゴリズムの複雑さの間には違いがあります。適切なalgorithmを使用していることを確認するのに十分な時間をかけてください。
  • 正しい質問をしていることを確認してください。select (select count(*) from foo) >= 1select exists(select 1 from foo)と同じではありません。
  • 一部の言語イディオムは、高速であるために人気があります。言語のほとんどの流暢なユーザーが使い慣れているため、これらを使用しても問題ありません。 (あなたの例は良い例です)。

何を最適化するかを決めるときは、常に アムダールの法則 を覚えておいてください。正確な計算についてはリンクを参照してください。覚えておくべき簡潔なステートメントは次のとおりです。

プログラムの一部が実行時間の10%を占め、その部分を2倍の速度で実行するように最適化すると、プログラム全体としては5%だけ高速化します。

これが、総実行時間の数パーセント以上を占めないプログラムの部分を最適化する価値はないと常に人々が言う理由です。しかし、これはより一般的な原則の特別なケースにすぎません。アムダールの法則によれば、プログラム全体を2倍の速度で実行する必要がある場合は、すべての部分を平均50%高速化する必要があります。これは、20ギガバイトのデータを処理する必要がある場合、ディスクから20ギガバイトを読み取るのにかかる時間よりも速くするには、2つの方法しかありません。より高速なディスクを入手するか、データを小さくします。

では、アムダールの法則はミクロ最適化について何と言っていますか?彼らは全面的に適用する場合、それらはおそらく価値があると述べています。プログラムのすべての関数の実行時間を1%削減できる場合は、おめでとうございます。プログラムを1%高速化しました。それはやる価値がありましたか?まあ、コンパイラーの人としては、それを実現する最適化を見つけて喜んでいますが、手作業で行う場合は、もっと大きなものを探してみます。

7
zwol

開発のどの段階にあるかによって異なりますが、最初に何かを書き始めるときは、マイクロ最適化を考慮する必要はありません。マイクロ最適化を使用するよりも、優れたアルゴリズムを使用する方がパフォーマンスが向上するからです。また、時間に敏感なアプリケーションは、一般的なビジネスアプリケーションよりもマイクロ最適化の考慮事項から多くのメリットを享受するため、開発中のものを検討してください。

ソフトウェアのテストと拡張を行っている場合、マイクロ最適化によってコードが読みにくくなり、修正が必要な独自のバグのセットと、修正が必要なその他のバグが発生する傾向があります。

遅いコードについてユーザーから実際に苦情を受けている場合、それらは検討する価値があるかもしれませんが、他のすべてが解決されている場合に限られます。

  • コードはよく書かれていますか?
  • アプリケーションは問題なくデータにアクセスできますか?
  • より良いアルゴリズムを使用できますか?

これらの質問にすべて答えてもパフォーマンスの問題が解決しない場合は、コードでマイクロ最適化の使用を開始する時期かもしれませんが、他の変更(つまり、より優れたコード、より優れたアルゴリズムなど)がうまくいく可能性がありますマイクロ最適化よりもパフォーマンスが向上します。

6
rjzii

実行速度は、プログラムの品質に影響を与える多くの要因の1つです。多くの場合、速度は可読性/保守性と逆の相関関係があります。ほとんどすべての場合、コードは人間が読めるようにして、コードを保守できるようにする必要があります。読みやすさが損なわれる可能性があるのは、速度が必須要件である場合のみです。完全な可読性/保守性が許可するよりも速くコードを作成する要件は、ほとんど適用できませんが、それが可能である特定のケースがあります。覚えておくべき主なことは、マイクロ最適化されたコードはしばしばハッキーなコードであるため、どこかに定義された要件がない限り、ほとんど常に問題を解決する間違った方法です。たとえば、ユーザーはCRUD操作での0.5秒と1秒の実行時間の違いにほとんど気付かないため、その0.5秒に到達するためにAssembly-interop-hackfestに移動する必要はありません。はい、ヘリコプターを飛ばして仕事をすることができ、それは10倍速くなりますが、価格とヘリコプターの方がはるかに飛行が難しいという事実のために、そうではありません。 不必要にコードをマイクロ最適化するとき、これはまさにあなたがやっていることです:不必要な複雑さとコストを追加して余分な目標を達成します。

5

制約にぶつかった場合、マイクロ最適化は重要です。重要なのは、メモリ、スループット、待ち時間、または電力消費です。これらはシステムレベルの特性であることに注意してください。すべての関数をあらゆる方法で最適化する必要はありません(また、最適化することもできません)。

組み込みシステムでは、制約がより簡単に発生するため、マイクロ最適化が必要になる可能性が高くなります。ただし、マイクロ最適化を行っても、これまでのところはうまくいきません。悪い設計から抜け出す方法をマイクロ最適化することはできません。システムの優れた設計についてのポイントは、システム全体について推論できることです。マイクロ最適化を必要とするコンポーネントは、システムの設計に影響を与えない方法で適切に公開および最適化する必要があります。

今日の小さな「組み込み」システムは、昨年の Vaxen または PDP-11s にかなり近い可能性があるため、これらの問題は以前より一般的でした。現代の一般的な商用コンピューティングを行う現代の汎用システムでは、マイクロ最適化はまれです。これはおそらくあなたの父親が彼がする立場を取る理由の一部です。

ただし、ナノ秒、ミリ秒、秒、時間のいずれを処理するかは関係ありません。問題は同じです。それらは、システムと達成しようとしているもののコンテキストで評価する必要があります。

これは、マイクロ最適化が必要な場合の Stack Overflow について回答した最近の質問の例です:組み込み用のオープンソースビデオエンコーダーシステム

5
janm

マイクロ最適化の最大の問題は、保守が難しいコードを作成することです。

別の問題は、コンピューターの構成によっては、「最適化」を行わない場合よりも、マイクロ最適化のパフォーマンスが最悪になることがあります。

多くのマイクロ最適化を行うと、本当に重要ではないものとの戦いに多くの時間が費やされます。

より良いアプローチは、よりクリーンなコードを作成し、保守を容易にすることです。パフォーマンスの問題が発生した場合は、プロファイルを実行して、コードが実際に遅くなっている原因を突き止めます。そして、本当に悪いことを正確に知ることで、それを修正できます。

マイクロ最適化を行わないことが愚かなコードを書くための言い訳だと言っているのではありません。

4
Daniel Moura

私は以前にそれを言ったことがあり、ここでそれを言います:"時期尚早の最適化はすべての悪の根源です"。これは、プログラマーの心の中心にあるルールの1つであるべきです。

コードは、ある程度までは、常に現在よりも高速である可能性があります。特定のチップを念頭に置いてアセンブリを手で梱包しない限り、最適化によって常に何かが得られます。ただし、行うすべてのことについてアセンブリをハンドパッキングしたい場合を除き、定量的な目標を設定する必要があります。目標が満たされたら、「十分です」と言って最適化を停止します。あなたの顔に。

美しく、エレガントで、非常にパフォーマンスの高いコードは、それが機能しない場合は役に立ちません(つまり、「機能する」とは、すべての予想される入力を想定して予想される出力を生成することを意味します)。したがって、機能するコードの作成は常に最優先事項です。それが機能したら、パフォーマンスを評価し、それが不足している場合は、十分に良いところまで、それを改善する方法を探します。

パフォーマンスに影響を与える前もって決定しなければならないことがいくつかあります。このソリューションの実装に使用する言語/ランタイムなどの非常に基本的な決定。これらの多くは、あるメソッドと別のメソッドを呼び出すよりも桁違いにパフォーマンスに影響します。正直なところ、スクリプト言語としてのPHPは既にパフォーマンスに影響を与えていますが、C/C++でボトムアップで構築されているスクリプトサイトは非常に少ないため、Javaサーブレット、ASP.NETから選択する他のテクノロジーに匹敵します。 、など)。

その後、I/Oメッセージのサイズは、次に大きなパフォーマンスキラーになります。ハードディスク、シリアルポート、ネットワークパイプなどの読み取りと書き込みを最適化すると、I/O操作の背後にあるアルゴリズムが効率的であったとしても、プログラムの実行時間が通常桁違いに向上します。その後、アルゴリズム自体のBig-Oの複雑さを軽減します。絶対に必要な場合は、より安価なメソッド呼び出しを選択し、他の難解な決定を低レベルで行うことにより、「マイクロ最適化」できます。

4
KeithS

ミリ秒について心配し始めた場合は、PHPをあきらめて、代わりにCまたはアセンブリを使用することを検討してください。これを行いたいとは思いませんが、そのような数値について説明しても意味がありません。スクリプト言語を使用します。コードは、とにかく頻繁にこのコマンドで繰り返されますか?

環境要因はここでは問題外です。これらのサーバーは24時間年中無休で稼働しており、実際に何かを処理する場合、それが非常に長時間実行されるタスクである場合にのみ問題になります。

ほとんどの場合、オフィスの照明と、質問と回答を入力するときにコンピューターが使用したエネルギーは、アプリケーションに合理的に適用できるあらゆる種類のマイクロ最適化よりもはるかに多くのエネルギーを消費します。

4

あなたのお父さんは引退したプログラマーだと言っています。メインフレームの世界で働いていたプログラマーは、パフォーマンスについて非常に心配する必要がありました。メインフレームがユーザーあたり64 KBのメモリにハードウェア的に制限されていた米国海軍の活動を研究したことを覚えています。そのプログラミングの世界では、あなたはあなたができるあらゆる小さなビットを精査する必要があります。

今では状況が大きく異なり、ほとんどのプログラマーはマイクロ最適化についてそれほど心配する必要はありません。ただし、組み込みシステムのプログラマーは依然としてそうであり、データベースの人々は最適化されたコードを使用する必要があります。

4
HLGEM

タスクに最適なシンプルなアルゴリズムを選択する必要があります。シンプルにする必要があるのは、コードを読みやすくするためです。それが最良である必要がある理由は、悪い実行時特性で始めることを避けるためです。大規模なデータセットが存在することがわかっている場合は、盲目的にBubbleSortを選択しないでください。ただし、10個の要素が時々ある場合は問題ありません。

次に、プロファイリングの数値が、選択した最良の単純なアルゴリズムでは不十分であることを示している場合は、最適化を開始できます(これは通常、読みやすさのコストとして)。

4
user1249

コーディング時にマイクロ最適化は重要ですか?

いいえ、 [〜#〜] jvm [〜#〜]。NET のようなプラットフォームがあり、コードが仮想マシン用に記述されているため、実行を最適化しようとしている開発者のデスクトップで最適なものがサーバーでも同じであるとは限らないため、うまく機能しない可能性があります。ここで別のポイントとして、これらの高レベルソフトウェアの一部がハードウェアからどれだけ離れているかを見てください。考慮すべきことはハードウェアの多様性を考えると、新しいモデルがおそらく1年以内に出てくるときに、CPUやGPUなどの特定のチップ用にコードを最適化することはどれほど現実的ですか?

ここで考慮すべきもう1つの問題は、次のメトリックによって測定されるパフォーマンスです。実行速度、実行に使用されるメモリ、新機能の開発速度、コンパイル済みまたは逆コンパイル済みのサーバーでのコードベースのサイズ、スケーラビリティ、保守性など。 。?十分に広く取れば質問は簡単になりますが、何らかの方法で測定できる限り、パフォーマンスを実際にどれほど広く取ることが意図されていたとしても、ほとんど何でもかまいません。


一部のマイクロ最適化は機能する場合と機能しない場合があり、新機能やバグの修正など、はるかに高い優先度であると見なされる可能性のある他の作業と比較して、そのような作業を実行する価値はどれほどあるか疑問に思われる場合があります。もう1つの問題は、ハードウェアまたはソフトウェアのアップグレードによって、これらの最適化の一部が機能しなくなるかどうかです。

3
JB King

コードは、それが何をするのかについて完全に明確になるように書かれるべきです。次に、ififのみです。遅すぎるため、戻って高速化してください。コードは、理解できる場合はいつでも後で速くなるように変更できますが、速い場合は明確に変更してください。

3
DeadMG

次の場合に重要です。

1)誰かの人生はあなたのコードに依存します。誰かの心拍数モニターで実行するのに25msかかる関数は、おそらく悪い考えです。

私は個人的に2つのアプローチをとります-可読性に影響を及ぼさない、実行できるマイクロ最適化があります-明らかにそれらを使用したいと思います。しかし、それが読みやすさに影響を与える場合は、延期してください。あまりメリットはなく、実際には、長期的にデバッグするのに時間がかかる可能性があります。

3
ansiart

IMHOコードの可読性は、マイクロ最適化よりも重要です。これは、ほとんどの場合、マイクロ最適化は価値がないためです。

記事 無意味なマイクロ最適化について

私たちのほとんどと同じように、printをエコーで置き換える、++ $ iを$ i ++で置き換える、二重引用符を一重引用符で置き換えるなど、意味のないマイクロ最適化に関するブログ投稿を読むのはうんざりです。どうして?時間の99.999999%のため、それは無関係です。どうして? 99.99%の時間なので、APCのようなPHPアクセラレータをインストールするか、これらの不足しているインデックスをデータベースの列に追加するか、ホームページにある1000のデータベースリクエストを回避することをお勧めします。 。

printは実際に何かを返すため、もう1つのオペコードを使用します。エコーは印刷よりも速いと結論付けることができます。しかし、1つのオペコードのコストはまったくかかりません。

新しいWordPress=インストールを試しました。ラップトップで「バスエラー」が発生してスクリプトが終了する前にスクリプトが停止しましたが、オペコードの数はすでに230万を超えていました。

したがって、ほとんどの場合、マイクロ最適化により数百万の操作のうち1つが節約されますが、読みやすさが低下します。

1
webvitaly

良いプログラミングとマイクロ最適化の間には大きな違いがあると思います。

同じタスクを実行する方法が2つあり、一方がもう一方よりも速く、両方が同じように読みやすい場合は、より速く使用する必要があります。常に。そして、これは良いプログラミングです。問題を解決するためにより良いアルゴリズムを使用しない理由はありません。そして、それを文書化することも簡単です:アルゴリズム名を指定すると、誰でもアルゴリズムをググって、それがどのように機能するかについての詳細情報を見つけることができます。

そして、優れたアルゴリズムはすでに最適化されています。彼らは速くなります。彼らは小さくなります。必要最小限のメモリを使用します。

それらを使用しても、プログラムにそのパフォーマンスがない場合でも、マイクロ最適化を検討できます。そして、マイクロ最適化を行うには、言語を本当に理解している必要があります。

そして、ハードウェアにいくらかお金を費やす余地は常にあります。 ハードウェアは安価で、プログラマーは高価です 。ハードウェアを購入できる時期を最適化することで、時間とお金をかけすぎないようにしてください。

1
woliveirajr

「価値がある」には、user応答性が非常に高く、インタラクティブで、待機する時間が短くて済みます。

特に最近私がソーダを飲むことはめったにないので、いくつかのペニーを節約してソーダの缶を購入することは、それらのペニーを救うために距離を移動する必要がある場合、あまり役に立ちません。 100万缶のソーダを購入して、1缶あたり数ペニーを節約することは、大変なことです。

一方、2人が私の隣にいて、1人がまったく同じものをいくつかのペニーより安く提供し、他の人はそれを提供しない場合、いくつかのペニーを節約します。私は彼らの帽子が好きなので愚かなケースのように見えるので、私はより高いものを選択します。悲観化の。

私が「マイクロ最適化」と呼んでいる人が不思議なことに測定値、コンテキスト、ユーザーエンドのディスカッションを欠いているように見えますが、そのような最適化を検討するのは簡単ではない場合、3つすべてを検討する必要があります。私にとって、最近の適切なマイクロ最適化は、メモリレイアウトやアクセスパターンなどに関連しており、「マイクロ」に焦点を当てているように見えるかもしれませんが、実際にはマイクロではありません。

少し前までは、演算を24秒から25ミリ秒(約960倍高速)に減らし、同じ出力(自動テストによって保護されています)を使用して、アルゴリズムの複雑さを変更せずに、体積熱拡散スキニングのために、 「マイクロ最適化」(その最大のものは、メモリレイアウトの変更によって約2秒になり、残りはSIMDやVTuneでのキャッシュミスの詳細な分析、メモリレイアウトの再配置などでした)。

Wolfireはここでこのテクニックを説明し、必要な時間に苦労しました: http://blog.wolfire.com/2009/11/volumetric-heat-diffusion-skinning/

私の実装は、彼がそれを1分未満に落とすのに苦労していた間に、ミリ秒でそれを行うことができました: enter image description here

私がそれを24秒から25ミリ秒に「マイクロ最適化」した後、それはワークフローの画期的なものでした。アーティストは、リグを少し変更するたびに24秒待つことなく、30 FPSを超えるリアルタイムでリグを変更できるようになりました。そして、プログレスバーやこの種のものが必要なくなったので、ソフトウェアのデザイン全体が実際に変更されました。すべてインタラクティブになりました。したがって、すべての改善がアルゴリズムの複雑さを改善することなくもたらされたという意味では、これは「マイクロ最適化」かもしれませんが、以前は面倒で非インタラクティブなプロセスを作ったのは、かなり「メガ最適化」でした。ユーザーの作業方法を完全に変えるリアルタイムのインタラクティブなものに。

測定値、ユーザーエンド要件、コンテキスト

ここでのRobertのコメントは本当に気に入りました。

さて、召し上がれ。この種の変更は「それに値する」ものではないと主張する人はいないでしょう。あなたは具体的な利益を実証することができました。多くのいわゆるマイクロ最適化はできません。

これは、多くの場合リアルタイム要件があり、パフォーマンスが非常に重要なフィールドで作業しているにもかかわらず、自分の邪魔にならないようにマイクロ最適化を検討するのはこのときだけです。

そして、測定だけでなく、ユーザー側の側面も強調します。私は、最初にユーザー/ファンとして、次に開発者として現在の分野(および以前はgamedev)に来たという点で、奇妙なボールです。ですから、テクニカルパズルを解くようなプログラマーを興奮させるいつものことに興奮することはありませんでした。私は彼らに負担を感じましたが、私が他のユーザーと共有したユーザーエンドの夢を通して彼らに耐えます。しかし、それは私が何かを最適化しているかどうかを確認するのに役立ちました、それは本当の利点でユーザーに本当の影響を与えるでしょう。それはぼんやりとマイクロ最適化することに対する私の安全策です。

これは、私の意見では実際にはプロファイラーと同じくらい重要です。なぜなら、キューブの細分割を数十億のファセットにミクロ最適化するようなことを行った同僚がいて、キャラクターや乗り物のような現実世界の生産モデルを窒息させただけだからです。彼らの結果はある「技術デモ」の意味で印象的でしたが、実際のユースケースと一致しないプロファイリングと測定およびベンチマークのケースだったため、実際のユーザーにはほとんど役に立たなかった。したがって、ソフトウェアを1つと同じように考えて使用することを学ぶか、またはユーザーと協力して(理想的には両方とも、少なくともユーザーと協力して)、ユーザーにとって何が重要かを最初に理解することが非常に重要です。マイクロを取得し、シェービングサイクルとキャッシュミスを開始する場合など、私にとって最も重要なことは、それを行う方法の外に優先順位を付けることで本当に上手になり始めることです(当然、すべての場所を知ることと一致します)プロファイラーとユーザーエンドの両方の理解が非常に重要であるので、そうしないでください)。

1
Dragon Energy

他の答えはお金で正しいです。ただし、時期尚早な最適化/マイクロ最適化と言語/フレームワーク構造の動作の理解を反映するパフォーマンスコードの記述(申し訳ありませんが見つかりませんでした)を区別する必要がある別のポイントを追加します最後に一言)。最後の1つはa優れたコーディング慣行であり、通常は行う必要があります!

説明します。不適切な最適化(早すぎる/マイクロ最適化の読み取り)は、実際にボトルネックであるかどうかを知るためにプロファイリングせずにコードのセクションを最適化する場合ではありません。それは、あなたの仮定、伝聞、そして文書化されていない行動に基づいて最適化するときです。それが文書化されていて、より効率的/ 論理な方法で何かを行う場合、それがどんなに小さくても、良い最適化と呼びます。他の人が述べたように、これらはどちらも短所があり、良いビジネスを稼ぐことに関してはほとんど長所がありませんが、そうでない場合は前者ではなく後者を行います完全に敗北 =読みやすさ。 可読性/保守性は最も重要であり、どこに線を引くかについてです。

良い最適化と悪い最適化の両方の無益性として、ここで他の人が指摘したポイントを繰り返します。

  1. 特定の問題への依存関係は変化する可能性があり、アプリケーションの最適化に費やす時間論理セクションを完了する前には時間の無駄です。比較的早い段階で最適化することを意味します。今日はList<T>があり、アプリの出荷時にはそれをLinkedList<T>に変更する必要があり、今ではすべてのベンチマークが時間と労力の無駄になっています。

  2. ほとんどの場合、アプリケーションの実際のボトルネック(測定可能な違いとして読み取られます)はコードの5%(主にSQLのもの)であり、他の95%を最適化しても顧客にメリットはありません。

  3. 通常、「技術的に」パフォーマンスの高いコードとは、冗長性が高く、エラーが発生しやすいコードを意味します。これにより、保守が難しくなり、費やす時間が長くなり、お金を稼ぐことが少なくなります。

  4. 全世界で1%のパフォーマンス向上で節約したカーボンフットプリントは、チームがそのコードのデバッグと保守で排出する必要がある温室効果ガスによって簡単に小さくなります。

特に悪い最適化の欠点は次のとおりです。

  1. 期待するパフォーマンスが得られないことがよくあります。 最適化が間違っている のSOでこの質問を参照してください。 実際にはそれは悪影響を及ぼしますこれは、文書化されていない動作の問題です。

  2. ほとんどの場合、最近のコンパイラーはとにかくそれを行います。

悪い最適化と良い最適化の例をいくつか挙げます。

悪い人 -

  1. Int32の代わりに小さい整数型を使用する。

  2. ++iの代わりにi++を使用

  3. forの代わりにforeach(私が見た中で最悪、ロジックを完全に無効にします)

  4. 閉じられた変数の回避

    string p;
    foreach (var item in collection)
        p = ...;
    
  5. 次のように、文字列連結中に文字列の代わりにcharを使用します。

    string me = 'i' + "me myself"; // something along that line - causes boxing
    

良い(.NETの世界から。自明である必要があります)-

  1. ダブルルックアップ

    if (Dictionary<K, V>.TryGetValue(K, out V))
        do something with V
    

    の代わりに

    if (Dictionary<K, V>.ContainsKey(K))
        do something with Dictionary<K, V>[K]
    
  2. すべてをロード

    DirectoryInfo.EnumerateFiles();
    

    の代わりに

    DirectoryInfo.GetFiles();
    
  3. 2段階キャスト:

    s = o as string;
    if (s != null)
        proceed
    

    の代わりに

    if (o is string)
        s = (string)o;
    
  4. 順序が関係ない場合

    if (counter < X || expensiveFunction())
    

    の代わりに

    if (expensiveFunction() || counter < X)
    
  5. ボクシング

    void M<T>(T o) //avoids boxing
    {
    
    }
    

    の代わりに

    void M(object o)
    {
    
    }
    

これらが顕著なパフォーマンス上の利点をもたらすかどうか私に尋ねれば、私はノーと言うでしょう。しかし、これらの構成要素の動作の理解に由来するため、これらを使用することをお勧めします。 1つしかできないのに、なぜ2つの電話をかけるのですか?哲学的見地から、その良いコーディングの実践。また、厳密には1と3は少し読みにくくなりますが、読みやすさを上回りますか?いや、あまりないので使います。今こそそれが鍵です。読みやすさの比でまともなパフォーマンスを維持します。 そしてそれがそうであるとき、それはあなたが線を引く場所についてです。

1
nawfal

メモリとCPUが不足している31年近く前にプログラミングを始めました。多分これが私があなたのお父さんに同意する理由です。

優れたコーダーは、コードのすべての行の最適化について心配する必要があると思います。しかし、私はこの文に追加します:それだけの価値があるそして常にしようとします計算が重要でない場所での最適化よりも可読性を優先します

たとえば、別のスレッドで、ある人が以下のコードについて尋ねました。どちらのソリューションを選択するか:CPUまたはメモリ。

public class Main {

    public static int totalRevenue;
    public static int totalProfit;

    public static int option1(int numSold, int price, int cost) {
        // Option 1 (memory)
        totalRevenue += numSold * price;
        totalProfit += numSold * price - numSold * cost;
        return numSold * price;
    }

    public static int option2(int numSold, int price, int cost) {
        // Option 2 (time)
        int saleRevenue = numSold * price;
        totalRevenue += saleRevenue;
        totalProfit += saleRevenue - numSold * cost;
        return saleRevenue;
    }
}

このコードは、次のバイトコードを生成します。

public class Main {
  public static int totalRevenue;

  public static int totalProfit;

  public Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method Java/lang/Object."<init>":()V
       4: return

  public static int option1(int, int, int);
    Code:
       0: getstatic     #2                  // Field totalRevenue:I
       3: iload_0
       4: iload_1
       5: imul
       6: iadd
       7: putstatic     #2                  // Field totalRevenue:I
      10: getstatic     #3                  // Field totalProfit:I
      13: iload_0
      14: iload_1
      15: imul
      16: iload_0
      17: iload_2
      18: imul
      19: isub
      20: iadd
      21: putstatic     #3                  // Field totalProfit:I
      24: iload_0
      25: iload_1
      26: imul
      27: ireturn

  public static int option2(int, int, int);
    Code:
       0: iload_0
       1: iload_1
       2: imul
       3: istore_3
       4: getstatic     #2                  // Field totalRevenue:I
       7: iload_3
       8: iadd
       9: putstatic     #2                  // Field totalRevenue:I
      12: getstatic     #3                  // Field totalProfit:I
      15: iload_3
      16: iload_0
      17: iload_2
      18: imul
      19: isub
      20: iadd
      21: putstatic     #3                  // Field totalProfit:I
      24: iload_3
      25: ireturn
}

理解しやすいように、「iload_」はスタックからデータをロードし、「istore_」はスタックにデータを保存します。

より多くのCPUサイクルを費やす1つのソリューションで、1つのメモリ割り当てを本当に節約したことに気づくのは簡単です。この種の質問は、経験豊富なプログラマーでも発生する可能性があります。

ただし、この例には問題があります。スタックメモリは、バイトレベルではなくブロック単位で事前に割り当てられます。スレッドが実行されるたびに、スタック操作で使用する特定の量のメモリが割り当てられます。したがって、これらの4バイトがスタックをオーバーフローするほど幸運でない限り(そして、より大きなスタックサイズを設定する必要がある場合)、両方の例を実行するために同じメモリ量を消費することになります。しかし、2番目の方法では、数学の計算に多くのサイクルを費やしており、コードの可読性が大幅に低下しています。

コードの小さな部分での最適化について議論することは悪ではないというサンプルを与えるためにここに持ってきました。誰かがこのスレッドを指す質問を閉じました。しかし、このスレッドはその特定の質問には答えません。 「最適化について心配しないでください」についてのみ説明します。そして、この愚かなマントラのために、人々はそれが深い理解に行くのは正しくないと感じています。

その質問には合理的な答えがあり、おそらく内部についてより良い答えを出すこともできます。いったん学ぶと、優れたプログラマーは本能的にそのパターンを繰り返すことができ、より優れたプログラマーになります。プログラマーはコードについて批判的に考え、マシンがコードを処理する方法をできるだけ理解する必要があります。

ここでは、私たち全員がささいなことを最適化する必要があると主張していません。マイクロ最適化よりも読みやすさを優先することをお勧めしました。

「最適化について心配しないでください」というマントラを繰り返しても、状況は改善されないと私は信じています。それはプログラマーを怠惰にするだけです。プログラマは、物事が舞台裏でどのように機能するかを知るように仕組まれなければなりません。このようにして、人々はより良​​いコードを書くことを追求することができ、そして最適化しないときは賢明に選択します

0

私はこのように言います-マイクロ最適化は、ボトルネックではない何かを最適化するプロセスです。たとえば、プログラムが2つの関数AとBを呼び出し、Aが完了するまでに100ミリ秒かかり、Bが2マイクロ秒かかる場合、関数Bを最適化し続けます。これは重要ではないだけでなく、それは間違いです。ただし、関数Bの最適化は、最適化と呼ばれ、マイクロ最適化とは呼ばれません。最適化の重要性は異なります。他に何もする必要がなく、プログラムにバグがないとしたら、はい、それは重要です。しかし、一般的には優先順位があります。関数Cを追加/作成する必要があるとします。関数Cを作成すると、その機能なしでプログラムを高速化するよりもお金が増えると思われる場合は、最適化を行ってください。それ以外の場合は、機能性を追求します。また、パフォーマンスに重点を置いた経験豊富なプログラマーは、最適化に多くの時間を費やさず、高速プログラムを作成するだけです。少なくとも、使用するツールと、意味のない(マイクロを読み取る)最適化を何年も費やしてはならないことを知っています。

0
user11408

ミクロの最適化とミクロの最適化があります。 VB=(VB6とVB.NETの両方ですが、フレームワークからのIsNullOrEmptyオファリングを無視して))では、常に_str <> ""_ではなくLen(str) <> 0を使用します。ただし、通常、他のコードを使用した場所で他のコードを「修正」することはありません。

はい、後者はより読みやすくなっていますが、この場合、前者は読みにくくありません。

コードを設計するとき、パフォーマンスはconsiderationである必要がありますが、可読性と保守性の低下ではありません。

0
Mark Hurd