「開発者の不適切な最適化の直感」を回避するにはどうすればよいですか?


22

この声明を発表した記事を見ました:

開発者は、適切な理由でコードを最適化することを好みます。それはとても満足で楽しいです。ただし、最適化のタイミングを知ることははるかに重要です。残念ながら、開発者は一般に、アプリケーションのパフォーマンスの問題が実際にどこにあるのかについて恐ろしい直感を持っています。

開発者はこの悪い直感をどのように回避できますか?コードのどの部分が本当に最適化が必要かを見つけるための優れたツールはありますか(Javaの場合)?このテーマに関する記事、ヒント、または良い読み物を知っていますか?


1
これは「直観に基づいて[決定を下す]ことをどのように回避するか」に帰着します。シンプル:ハードファクトとデータで検証します。したがって、最適化の場合、開発者の観点からは、あなたはベンチマークです。
ヘイレム

回答:


44
  • 優れたプロファイラーを使用して、高価なメソッドを特定します。
  • ホットスポットが実際にかかった時間を記録します。
  • ホットスポットのより高速な実装を記述する
  • ホットスポットが現在どのくらいかかっているかを記録し、できればホットスポットにしないようにします。

基本的に、問題がどこにあったのかを他の人に証明する必要があり、この変更によりそれが消滅したことを証明する必要があります。

私の個人的な意見では、改善を証明できないことは、元のバージョンにすぐにロールバックする資格があります。


51
または、さらに簡単に言うと、「最適化の直感が悪いのを避けるために、直感を使用しないでください。測定します。」
キラレッサ

6
それがあなたの答えであり、私のコメントである理由です。:P
キラレッサ

2
@Thomas、読みやすさと保守性をいじって、パフォーマンスの問題を正確に見ていませんか?

3
@トーマス、私は同意しません。仕様内であっても、新しいコードを徹底的に再テストする必要があります。これは古いコードには必要ありません。元に戻す。

2
@Thorbjørnパフォーマンスの調整後、新しいコードを徹底的に再テストする必要もあります。欠陥を導入した場合、時間またはメモリを節約しても意味がありません。
トーマスオーエンズ

10

最適化する場所を知る唯一の方法は、コードをプロファイルすることです。メリットがあると思われる変更を加える代わりに、最悪のパフォーマンスのコードがどこにあるかを確実に把握し、そこから始めます。

Javaは、最近のリリースのJava Development Kit(JDK)にバンドルされているVisualVMツールでこれを非常に簡単にします。アイデアは、コードと外部ライブラリの両方で、最も呼び出されるメソッドと、ほとんどの時間を費やしているメソッドを見つけることです。ガベージコレクションのパフォーマンスデータを取得して、コレクタを調整し、アプリケーションに必要な最小/最大ヒープスペースを調整することもできます。


VisualVMはJREにはなく、JDKにのみあります。

1
@ThorbjørnRavn Andersenいいですね。明確にする必要があります。ただし、Java開発を行う場合は、通常、JDKがインストールされています(OpenJDKなどを実行している場合があります-VisualVMに付属しているかどうかはわかりません)。
トーマスオーエンズ

1
私は非常に頻繁にEclipseのワークスペースを切り替えますが、これはデフォルトでEclipseを起動したJREになります。JREのインストールはJDKのインストールよりもはるかに簡単であるため、Eclipseコンパイラを含むantビルドプロセスにゆっくりと移行し、プレーンなJREで実行できます。したがって、最近では実際にJDKなしで実際の作業を行うができ。VisualVMは個別にダウンロードできるため、Windows 64ビットJVMでは32ビットJVMに接続できず、逆の場合も同様に、特定のJavaバージョンでの使用が容易になります。

9

ここの誰かがプロファイラーについて話しているので、質問のこの部分に焦点を当てます。

開発者はこの悪い直感をどのように回避できますか?

君は。行う。ありません。代わりに、を早期に最適化することはありません
宗教的なマントラなので、何度も何度も繰り返してください。

あなたはそれをしていることに気づき、そうすべきでないことに気付くでしょう。
そして再び。
そしてまた。

アーリーオプティマイゼーションは、プログラマの重大な罪の 1つです。

ツールやものは後の最適化の一部であり、確立された技術


確かに、初期の「複雑なコード」の最適化。問題に適合し、(予想される処理負荷で)優れたパフォーマンス特性を持つアルゴリズムやデータ構造を選択することは、コードの記述を開始する前に実行する必要があるものです。
バティーン

@Vatineはい、行ったことがあります。いいえ、そうではありません。目前の問題のマインドマップに合ったものを実行してください。これは最もパフォーマンスの高いアルゴリズムである可能性ありますが、そうする必要はありません。
ZJR

YAGNIの原則として私に聞こえる-あなたはそれを必要としません!
ELユスボフ

7

これらのツールは プロファイラーます。これらを使用して、プログラムのどの部分を実行するのに最も時間がかかるかを実際に測定し、チューニング作業の焦点を合わせることができます。

変更に意図した効果があることを確認するために、変更に再度測定することも同様に重要です。


5

プログラムの速度や実行時間だけでなく、プログラムが使用するメモリ量も確認してください。

Javaなどのガベージコレクションされた言語を扱う多くのコーダーは、ガベージコレクションがメモリリークを防ぐという誤った印象を受けています。そうではありません。不要になったオブジェクトへの参照を保持している場合、そのオブジェクトは収集されないため、リークします。

サーバーがスワップ領域を使い果たすほど漏れやすいJava Webアプリケーションを見てきました!

ランタイムプロファイラーと何らかの方法のメモリプロファイラーの両方を使用する場合、より高速で無駄のないコードを直感的に記述する方法を学習します。これには、最初の試行でコードが高速に実行される可能性が高いという効果があります。


1

私の治療法は、2つの質問に対する明確な回答を得ることから始めることです。

  1. パフォーマンスの測定方法(例:データのロード時間の測定
  2. 目標値は何ですか(例:95秒の信頼性で3秒以内にデータがロードされる

私たちの製品の壊れたリリースを保存するためにかつて招待された虎のチームの人から上記のトリックを学びました。そのリリースはパフォーマンス上の理由で壊れていたため、トラの関与を正当化する戦略的な顧客を失う可能性がありました(かなり高価なところで)。私は彼らがプロジェクトの詳細を明確にするのを支援するように割り当てられました。また、これをパフォーマンスについて少し学ぶ機会として利用しました。


1

私が見つけたのは、時期尚早の最適化に対する最良の解毒剤であり、この方法です。

これを使用してコードを高速化すると(この例のように)、それ自体が中毒になり、パフォーマンスチューニングの最初の原則はコードを微調整することではなく、問題を発見することです。

あなたの家族を養うための狩猟はブリキ缶を撃つことであるので、本当の最適化は時期尚早の最適化です。採石場を見つけることがすべてです。


1
残念ながら、あなたは家族に200ポンドしか持ち帰ることができないので、一日中リスを撃ってはいけません。
ヨルダン

1

古い質問ですが、この答えは他のものとはかなり異なります。

パフォーマンスを向上させる大きな機会は、並列処理にあります。 複数のスレッドを活用するようにコードを設計してください。(たとえ簡単にするために、バージョン1ではそうしないとしても)。ちょっとした当て推量や直感が必要です。

それ以外のものは時期尚早な最適化であり、直観を必要としますが、これはしばしば間違っています。


本当に良い点。かつては、プロセッサが数年ごとにはるかに高速化することを期待できました。これで、プロセッサの数が増えると予想されるはずです。
ジミージェームズ

0

あなたの直感時間とともに向上します。多分少々物議をかもしますが、VTuneとCodeAnalyst、そして今はCodeXLを長年使用してきたので、少なくとも直近ではホットスポットがどこになるかについて、以前よりもはるかに正確になったと思いますコードのプロファイルを作成するときに、完全に不意を突かなくなったポイント。それは私が物事を盲目的に最適化しようとすることを意味しません。

プロファイリングは、プロファイラーへの依存度を実際に増加させたものであり、軽減するものではありません。プロファイリングの結果がある程度容易に予測でき、さらにホットスポットを正常に排除し、暗闇や行方不明者に盲目的な刺し傷をすることなくユーザーエンド操作を完了するのにかかる時間を改善できると言っているだけですプロファイラを使用していても、ホットスポットとは何かだけでなく、キャッシュミスなどの理由で正確にホットスポットである理由を理解できるようになるまで実行できます)。

ただし、プロファイラーを使い始めてから直観を改善し始めました。理由の1つは、コードに精通している場合、最大かつ最も明白なホットスポットに関しては正しいかもしれませんが、その間のすべての微妙さではないからです。当然、完了するのに1時間かかるユーザーエンド操作があり、100,000要素にわたる入力を処理する1つのギャップのある2次複雑度アルゴリズムがある場合、おそらく2次複雑度であるという考えで人生全体の節約を豊かに賭けることができますここで障害のあるアルゴリズム。しかし、それはあなたに詳細な洞察を与えるものではなく、たとえば、時間に貢献していないものを正確に知らせるものでもありません

プロファイリングを開始し、時間の大きな貢献であると思われるすべてのものがあまり時間を費やしていなかった場所を確認するときに、非常に多くの価値があります。明らかな非効率性の原因ではなく、疑わしいものはわずかに非効率的だったかもしれませんが、プロファイリング後、それらがいつでもほとんど寄与していないことに気付きました。そして、最も直感的な洞察を得る可能性があるのは、正確にどれだけの時間を費やしているかが明らかでない微妙な領域すべてで自分が間違って表示されることです。

明らかなアルゴリズムの複雑さを超えた人間の直感は、機械にとって効率的なものと人間の心にとって効率的なものが非常に異なるため、しばしば間違った状態から始まります。レジスタからCPUキャッシュ、DRAM、ディスクに至るメモリ階層について考えることは、最初はそれほど直感的ではありません。ルックアップテーブルの分岐やメモリアクセスを増やして処理作業をスキップするよりも、冗長な演算の方が高速であると考えるのは直感的ではありません。私たちは、意思決定のコストやメモリの負荷とストアなどを割り引きながら、どれだけの作業を行うべきかという観点から考える傾向があります。ハードウェアにとって効率的なことは、多くの場合、人間の前提をすべて破り始めるという点で非常に直感に反します。

その直観を改善できるのは、プロファイリングを通してインターフェース設計です。インターフェースの設計は、後から見直すと非常にコストがかかり、そのインターフェースに応じて場所の数に比例してコストが上昇します。直感の改善を開始すると、コストのかかる設計変更を行わずに将来の最適化のための余裕を残す方法で、インターフェイスの設計を最初から改善できます。繰り返しになりますが、その直観は一般的に開発するものであり、常にそのプロファイラーを手元に置いておくことで、無期限に開発を続けます。


0

プロファイラーは、コードに関しては悪い直観を修正するのに役立ちます。最近のハードウェアの予測量を考えると、コードのパフォーマンスを予測することは人間的に実用的ではありませんが、プロファイラーを修正するための標準ツールの一部としてプロファイラーを含めることを提唱した何十年も前のKnuthの時代にはまだ真実でした開発者の「ペニーワイズバウンドバカ」の性質。しかし、答えが他の点でどの程度包括的であるかを考えると、この答えでは非常に異なるルートに進み、ユーザー側の理解が他の「修正」であると言います。

私の個人的な経験では、特に素晴らしい開発者(しかし、ユーザーが実際にソフトウェアを使用する方法についての大きな盲点を持っている)を目撃しました。メッシュのGPUプロファイラーでのサンプリング)は、6つのケージ/入力ポリゴンを持つキューブのような単純なプリミティブを細分化するときに、GPUの数十億のファセットで驚くべき結果を達成します。彼が実際のユースケースとは異なるテストケースに対して調整および調整したことを除いて(ユーザーは、完全な球体に似た細分化された立方体に数十億のファセットを望んでいません。およびその他の複雑な入力)。

おもしろいことに、彼の半分の機能を備えた脳で、ユーザーの欲求、マーケティングの欲求、デザイナーの欲求を理解したという理由だけで、私のキャリアの中で博士号はありませんでした。ユーザーの考え方や靴に身を任せて、自分のソフトウェアと、実際のユーザーとして何をする必要があるかを見て、自分の努力から自分自身を離すことができることは、どれほど便利なのかを十分に強調することはできません構築したものを構築し、新鮮な目でそれを見てください。上記の開発者から、これは不可能なことでさえあることに気付きました。彼は、私はすべての技術的に精通しているがユーザーに気づかない開発者が持っている同様のエゴを持っていることで有罪だと思っていました。ユーザーとデザイナーが私に何をすべきかについて話すために私に群がるとき、私は彼が間違っていることを常に証明しました。それは非常に利己的に聞こえますが、私はそのような素晴らしいコーダーではないという免責事項とバランスをとりますが、ユーザーとデザイナーが何を望んでいるかを理解しているので、これが特に珍しいと思われる分野で私を特に支持させました何らかの理由で品質。プログラマとして、私たちはおそらく、普通の非技術的な人々と理解し、交流することよりも、テストを実施することに慣れています。

したがって、プロファイリングと適切な測定がありますが、実際のユーザーが実際にアプリケーションに提供する入力のタイプで操作を測定していることを実際に確認する基本的な必要性もあります。それ以外の場合は、VTune、CodeAnalyst、またはgprofまたはその他のプロファイラーを手元に置いて、開発者には通常のテストケースに見えてもユーザーにはわかりにくいテストスポットに対してホットスポットを最適化しようとすると、一般的なユースケースが悲観的になります少数のユーザー(存在する場合)が申請を検討するという、あいまいなユースケースを支持します。

結局のところ、開発者は、世界の飢solvingを解決することなくユーザーを本当に幸せにするものの鉄のハンマーとバランスを取ることができ、家賃を払ったり、ビールを購入したり、裸の女性またはあなたがしたい/必要なものを見てください。他のすべては、その基本的なビジネスニーズに潜在的に取り組んでおり、開発者は非常に高貴でとても勇敢であり、これはお金を稼ぐことと最終的にユーザーを満足させることを忘れることができます。そして、神のモードをオフにして仮想世界を作成し、現実世界のニーズを支持して、単に食料を出荷してお金を稼ぐだけです。ソフトウェアのメトリクスとプラクティスに迷うこともありますが、基本的にはそうです」

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.