時期尚早の最適化の呪いを回避する方法
公開: 2022-03-11それはほとんど保証に値する、本当に。 初心者から専門家まで、アーキテクチャからASMまで、そしてマシンのパフォーマンスから開発者のパフォーマンスまで何でも最適化することで、あなたとあなたのチームがあなた自身の目標を短絡させている可能性は非常に高いです。
何? 自分? 私のチーム?
それはレベルに対するかなり大きな非難です。 説明させてください。
最適化は聖杯ではありませんが、取得するのは同じくらい難しい場合があります。 チームの経験を自己破壊の1つから調和、充実、バランス、そして最終的には最適化の1つに変えるのに役立つ、いくつかの簡単なヒント(および落とし穴の山)を共有したいと思います。
時期尚早の最適化とは何ですか?
時期尚早の最適化は、パフォーマンスを最適化しようとしています。
- アルゴリズムを最初にコーディングするとき
- ベンチマークが確認する前に、次のことを行う必要があります
- プロファイリングの前に、わざわざ最適化することが理にかなっている場所を特定します
- あなたのプロジェクトが現在指示しているよりも低いレベルで
今、私は楽観主義者、オプティマスです。
少なくとも、この記事を書いている間、私は楽観主義者のふりをするつもりです。 あなたの側では、あなたの名前がOptimusであるふりをすることができるので、これはあなたにもっと直接話すでしょう。
技術者として、おそらく$year
になるのではないかと思うことがあるかもしれませんが、私たちの進歩にもかかわらず、 $task
が非常に煩わしいほど時間がかかることはどういうわけか許容できる基準です。 あなたは痩せたいです。 効率的。 素晴らしい。 それらの求人情報が求めているロックスタープログラマーのような人ですが、リーダーがチョップしています。 したがって、チームがコードを作成するときは、最初から正しく実行するように促します(ここでは、「正しい」という用語が非常に相対的な用語である場合でも)。 彼らはそれが賢いコーダーのやり方であり、後でリファクタリングの時間を無駄にする必要のない人々のやり方でもあることを知っています。
私はそのように感じる。 完璧主義の力が私の中で強いこともあります。 みんなが「他の人が書いたShittyCode(何を考えていたのか?)」のシェアをくぐり抜けているので、チームに少し時間をかけて後で多くの時間を節約してもらいたいと思います。 あなたが発音できない頭字語が好きだと知っているので、それは略してSCOPWWHWTTです。
また、チームのコードを自分自身や将来の誰かのためのコードにしたくないことも知っています。
それでは、チームを正しい方向に導くために何ができるか見てみましょう。
最適化するもの:これは芸術であることへようこそ
まず第一に、プログラムの最適化について考えるとき、私たちはしばしばパフォーマンスについて話しているとすぐに思い込みます。 それでも、見た目よりも曖昧になっているので(速度、メモリ使用量など)、そこで停止しましょう。
さらに曖昧にしましょう! 最初は。
私のcobwebbyの頭脳は、可能な限り秩序を作り出すのが好きなので、私がこれから言おうとしていることを良いことだと考えるには、楽観的な見方が必要です。
(パフォーマンス)最適化の簡単なルールがあります。それはしないでください。 これは厳密に従うのは非常に簡単に聞こえますが、誰もがそれに同意するわけではありません。 私も完全には同意しません。 一部の人々は、他の人々よりもゲートからより良いコードを書くだけです。 うまくいけば、特定の人にとって、新しいプロジェクトで作成するコードの品質は、一般的に時間の経過とともに向上します。 しかし、多くのプログラマーにとって、これは当てはまらないことを私は知っています。なぜなら、彼らが知っているほど、彼らが時期尚早に最適化するように誘惑されるからです。
多くのプログラマーにとって…彼らが知っているほど、彼らは時期尚早に最適化するように誘惑されるでしょう。
したがって、これは正確な科学ではあり得ませんが、パズルを解くという典型的な技術者の内なる衝動に対抗することだけを目的としています。 結局のところ、これが多くのプログラマーをそもそもクラフトに引き付けるものです。 わかりました。 しかし、誘惑に抵抗するために、それを保存するように彼らに頼んでください。 今すぐパズルを解くアウトレットが必要な場合は、日曜日の紙の数独に手を出すか、メンサの本を手に取るか、人工的な問題を抱えてコードゴルフに行くことができます。 ただし、適切な時間になるまでリポジトリから除外してください。 ほとんどの場合、これは事前最適化よりも賢明な方法です。
この慣行は、時期尚早の最適化がすべての悪の根源であるかどうかを人々が尋ねるほど悪名高いことを忘れないでください。 (私はそれほど遠くまでは行きませんが、私は感情に同意します。)
デザインのあらゆるレベルで考えられる最も頭の痛い方法を選ぶべきだと言っているのではありません。 もちろん違います。 しかし、最も賢く見えるものを選ぶ代わりに、他の値を考慮することができます。
- 新入社員に説明するのが最も簡単
- 最も経験豊富な開発者によるコードレビューに合格する可能性が最も高い
- 最もメンテナンスしやすい
- 書くのが一番速い
- テストするのが最も簡単
- 最もポータブル
- 等
しかし、ここで問題が難しいことがわかります。 速度、コードサイズ、メモリフットプリント、柔軟性、または将来性の最適化を回避するだけではありません。 それはバランスについてであり、あなたがしていることが実際にあなたの価値観や目標と一致しているかどうかについてです。 それは完全に文脈的であり、時には客観的に測定することさえ不可能です。
なぜこれが良いことなのですか? 人生はこんな感じだから。 散らかっています。 私たちのプログラミング志向の頭脳は、混沌の中で秩序を作りたいと思うことがあるので、皮肉なことに混沌を倍増させてしまいます。 それは誰かにあなたを愛するように強制しようとするパラドックスのようなものです。 あなたがそれで成功したと思うなら、それはもはや愛ではありません。 その間、あなたは人質取りの罪で起訴されており、おそらくこれまで以上に多くの愛が必要であり、この比喩は私が選ぶことができた中で最も厄介なものの1つでなければなりません。
とにかく、あなたが何かのための完璧なシステムを見つけたと思うなら、まあ…それが続く間、幻想を楽しんでください、私は推測します。 それは大丈夫です、失敗は学ぶための素晴らしい機会です。
UXを念頭に置いてください
ユーザーエクスペリエンスがこれらの潜在的な優先事項の中にどのように適合するかを調べてみましょう。 結局のところ、何かがうまく機能することを望んでいることでさえ、あるレベルでは、UXについてです。
UIで作業している場合、コードが使用するフレームワークや言語に関係なく、ある程度の定型文と繰り返しがあります。 それを減らすことを試みることは、プログラマーの時間とコードの明快さの点で間違いなく価値があります。 優先順位のバランスをとる技術を支援するために、いくつかの話を共有したいと思います。
ある仕事で、私が働いていた会社は、意見の分かれた技術スタックに基づいたクローズドソースのエンタープライズシステムを使用していました。 実際、それを私たちに販売したベンダーは、開発者にとって非常に苦痛だったため、スタックの意見に合わないUIのカスタマイズを行うことを拒否したとの意見がありました。 私は彼らのスタックを使用したことがないので、これについて非難することはありませんが、この「プログラマーにとっては良い、ユーザーにとっては悪い」というトレードオフは、特定のコンテキストで同僚にとって非常に面倒だったため、終了しましたシステムのUIのこの部分を再実装するサードパーティのアドオンを作成します。 (これは生産性を大幅に向上させました。私の同僚はそれを気に入っていました。10年以上経った今でも、時間とフラストレーションを節約できています。)
意見自体が問題だと言っているのではありません。 私たちの場合、それが多すぎることが問題になりました。 反例として、Ruby on Railsの大きな魅力の1つは、選択肢が多すぎることでめまいが起こりやすいフロントエンドエコシステムで、それが意見を述べられていることです。 (私が自分自身を理解できるまで、私に意見を持って何かをください!)
対照的に、プロジェクトでUXをすべての王に冠したくなるかもしれません。 価値のある目標ですが、2番目の話をさせてください。
上記のプロジェクトが成功してから数年後、同僚の1人が私に来て、ワンクリックで解決できるように、時々発生する特定の厄介な現実のシナリオを自動化してUXを最適化するように依頼しました。 シナリオの多くの奇妙なエッジケースのために、誤検知や誤検知が発生しないアルゴリズムを設計することさえ可能かどうかを分析し始めました。 それについて同僚と話をすればするほど、要件が単に報われないことに気づきました。 シナリオはたまにしか発生しませんでした(たとえば、毎月)、現在、1人の人が解決するのに数分かかりました。 バグがなくても自動化に成功したとしても、同僚が節約した時間の観点から、必要な開発と保守の時間が報われるまでには何世紀もかかるでしょう。 私の中の人々を喜ばせる人は「いいえ」と言うのに苦労しましたが、私は会話を短くしなければなりませんでした。
ですから、ユーザーを助けるためにできることをコンピューターに任せましょう。 しかし、それがどの程度かをどうやって知るのですか?
私が採用したいアプローチは、開発者がコードをプロファイリングするようにUXをプロファイリングすることです。 ユーザーが同じものを何度も何度もクリックまたは入力するのに最も時間を費やしている場所を見つけて、それらのインタラクションを最適化できるかどうかを確認します。 あなたのコードは、彼らが入力する可能性が最も高いものについていくつかの知識に基づいた推測を行い、それを入力なしのデフォルトにすることができますか? 特定の禁止されているコンテキスト(クリックしないEULA確認?)を除いて、これはユーザーの生産性と幸福に実際に違いをもたらす可能性があります。 可能であれば、廊下のユーザビリティテストを行ってください。 時々、コンピュータが助けやすいものとそうでないものを説明するのに苦労するかもしれません…しかし、全体として、この値はあなたのユーザーにとってかなり重要である可能性があります。
時期尚早の最適化の回避:最適化する時期と方法
他のコンテキストの調査にもかかわらず、この記事の残りの部分では、生のマシンのパフォーマンスのいくつかの側面を最適化していると明示的に仮定しましょう。 私が提案するアプローチは、柔軟性などの他のターゲットにも適用されますが、各ターゲットには独自の落とし穴があります。 重要な点は、何かを時期尚早に最適化するとおそらく失敗するということです。

では、パフォーマンスの観点から、実際に従うべき最適化方法は何ですか? 掘り下げてみましょう。
これは草の根のイニシアチブではなく、トリプルです
TL;DRは次のとおりです。上から下に向かって作業します。 より高いレベルの最適化はプロジェクトの早い段階で行うことができ、より低いレベルの最適化は後で行う必要があります。 「時期尚早の最適化」というフレーズの意味のほとんどを理解するために必要なのはこれだけです。 この順序で物事を行うと、チームの時間を無駄にし、逆効果になる可能性が高くなります。 結局のところ、プロジェクト全体を最初からマシンコードで記述しているわけではありませんか? したがって、AAAの手口は次の順序で最適化することです。
- 建築
- アルゴリズム
- 組み立て
一般的な知恵では、少なくともパフォーマンスが懸念される場合、アルゴリズムとデータ構造が最適化するのに最も効果的な場所であることがよくあります。 ただし、アーキテクチャによって、使用できるアルゴリズムとデータ構造が決まる場合があることに注意してください。
私はかつて、財務レポートを実行するソフトウェアの一部を発見しました。これは、単一の財務トランザクションごとにSQLデータベースに複数回クエリを実行し、クライアント側で非常に基本的な計算を実行することです。 中小企業がソフトウェアを使用するのに数か月しかかからなかったのは、比較的少量の財務データでさえ、新しいデスクトップとかなり頑丈なサーバーを使用した場合、レポートの生成時間はすでに数分でした。かなり頻繁に使用する必要があったもの。 最終的に、合計ロジックを含む単純なSQLステートメントを作成しました。つまり、すべての重複とネットワークラウンドトリップを回避するために作業をサーバーに移動することでアーキテクチャを阻止し、数年後のデータでも、私のバージョンで生成される可能性があります。同じ古いハードウェアでわずか数ミリ秒で同じレポート。
プロジェクトのアーキテクチャを変更するには遅すぎるため、プロジェクトのアーキテクチャに影響を与えない場合があります。 上記の例で行ったように、開発者がそれを回避できる場合があります。 しかし、プロジェクトの開始時にそのアーキテクチャについて意見がある場合は、今がそれを最適化するときです。
建築
プロジェクトでは、アーキテクチャは事後に変更するのに最も費用のかかる部分であるため、最初に最適化することが理にかなっている場所です。 たとえば、アプリがダチョウを介してデータを配信する場合は、悪いボトルネックをさらに悪化させないように、低頻度で高ペイロードのパケットに向けてデータを構造化する必要があります。 この場合、読み込みスピナーがそれをカットすることはないので、ユーザーを楽しませるためにテトリスの完全な実装を持っている方が良いでしょう。 (冗談はさておき:数年前、私は最初のLinuxディストリビューションであるCorel Linux 2.0をインストールしていましたが、長期にわたるインストールプロセスにそれが含まれていることを嬉しく思います。Windows95インストーラーのインフォマーシャル画面を何度も見て、覚えていました。当時は新鮮な空気の息吹でした。)
アーキテクチャの変更に費用がかかる例として、前述のSQLレポートがそもそも非常に拡張性が低い理由は、その歴史から明らかです。 このアプリは、MS-DOSにルーツがあり、元々はマルチユーザーでさえなかった自家製のカスタムデータベースから、時間の経過とともに進化してきました。 ベンダーが最終的にSQLに切り替えたとき、スキーマとレポートコードは1対1で移植されたようです。 これにより、特定のレポートでSQLの利点を実際に利用してアーキテクチャの切り替えを完了するたびに、更新全体に1,000%以上のパフォーマンスの改善を何年にもわたって振り向けることができました。 私の当時の雇用主のようなロックインされたクライアントとのビジネスに適しており、最初の移行時にコーディング効率を明確に優先しようとしています。 しかし、場合によっては、ハンマーがネジを回すのと同じくらい効果的にクライアントのニーズを満たすことができます。
アーキテクチャとは、プロジェクトをどの程度、どのように拡張できる必要があるかを予測することです。 アーキテクチャは非常に高レベルであるため、特定のテクノロジとドメインに焦点を絞らずに、「すべきこととすべきでないこと」を具体的に理解することは困難です。
私はそれをそれとは呼びませんが、他の誰もがそうします
ありがたいことに、インターネットには、これまでに夢見たほとんどすべての種類のアーキテクチャに関する収集された知恵が溢れています。 アーキテクチャを最適化する時期が来たことがわかったら、落とし穴を調査することは、あなたの素晴らしいビジョンを説明する流行語を理解することになります。 誰かがあなたと同じように考え、試し、失敗し、繰り返し、ブログや本でそれについて公開した可能性があります。
流行語の識別は、検索するだけでは難しい場合があります。これは、FLDSMDFRと呼ばれるものについて、他の誰かがすでにSCOPWWHWTTという用語を作り出しており、解決しているのと同じ問題を説明していますが、使用する語彙がまったく異なるためです。 開発者コミュニティが救いの手を差し伸べます! StackExchangeまたはHashNodeに、できるだけ詳細な説明と、アーキテクチャがそうではないすべての流行語を追加して、十分な予備調査を行ったことを知らせます。 誰かが喜んであなたを啓発します。
その間、いくつかの一般的なアドバイスは考えるのに良い食べ物かもしれません。
アルゴリズムとアセンブリ
助けとなるアーキテクチャを考えると、ここでチームのコーダーが時間の中で最もT-blingを取得します。 時期尚早の最適化の基本的な回避はここでも当てはまりますが、プログラマーはこのレベルでいくつかの詳細を検討することをお勧めします。 実装の詳細に関しては、考えることがたくさんあるので、最前線のコーダーと上級コーダーを対象としたコードの最適化について別の記事を書きました。
しかし、あなたとあなたのチームがパフォーマンス面で最適化されていない何かを実装したら、あなたは本当にそれを「しないでください」に任せますか? あなたは決して最適化しませんか?
あなたが正しい。 次のルールは、専門家のみのために、まだそれをしないことです。
ベンチマークの時間です!
コードは機能します。 たぶん、それは非常に遅いので、頻繁に実行されるコードであるため、最適化する必要があることをすでに知っています。 よくわからないか、O(n)アルゴリズムを使用していて、おそらく問題ないと考えています。 いずれにせよ、このアルゴリズムを最適化する価値があるとしたら、この時点での私の推奨事項は同じです。単純なベンチマークを実行します。
なんで? 私のO(n³)アルゴリズムが他の何よりも悪くなる可能性がないことは明らかではありませんか? ええと、2つの理由で:
- 現在達成されているかどうかに関係なく、パフォーマンス目標の客観的な尺度として、ベンチマークをテストスイートに追加できます。
- 専門家でさえ、うっかりして物事を遅くする可能性があります。 当たり前のように思えても。 本当に明らかです。
その2番目の点で私を信じていないのですか?
7,000ドルのハードウェアよりも1,400ドルのハードウェアからより良い結果を得る方法
StackOverflowで有名なJeffAtwoodは、プログラマーの貴重な時間を最適化に費やすよりも、より良いハードウェアを購入する方が費用効果が高い場合があると指摘しました。 OK、プロジェクトがこのシナリオに適合するという合理的に客観的な結論に達したとしましょう。 さらに、最適化しようとしているのはコンパイル時間であると仮定しましょう。これは、作業中のSwiftプロジェクトであり、これが開発者の大きなボトルネックになっているためです。 ハードウェアショッピングタイム!
何を買うべきですか? まあ、明らかに、円は円で、より高価なハードウェアはより安価なハードウェアよりもパフォーマンスが良い傾向があります。 つまり、明らかに、7,000ドルのMac Proは、ミッドレンジのMacMiniよりも速くソフトウェアをコンパイルする必要があります。
違う!
コアが多いほど、コンパイルが効率的になる場合があります。この特定のケースでは、LinkedInは、スタックに対して逆のことが当てはまるという難しい方法を発見しました。
しかし、私は経営陣がさらに1つの間違いを犯しているのを見てきました。彼らは前後のベンチマークすらしていなかったし、ハードウェアのアップグレードによってソフトウェアの「感触」が速くならないことがわかりました。 しかし、確実に知る方法はありませんでした。 さらに、彼らはまだボトルネックがどこにあるのかわからなかったので、問題に割り当てようとしていた時間とお金を使い果たして、パフォーマンスに不満を抱いていました。
OK、私はすでにベンチマークを行っています。 私は実際にまだ最適化できますか?
はい、必要だと判断したと仮定します。 しかし、おそらくその決定は、他のすべてのアルゴリズムも実装されるまで待つので、可動部分がどのように組み合わされ、プロファイリングによって最も重要であるかを確認できます。 これは、小さなアプリのアプリレベルの場合もあれば、1つのサブシステムにのみ適用される場合もあります。 いずれにせよ、特定のアルゴリズムはアプリ全体にとって重要に見えるかもしれませんが、専門家、特に専門家でさえ、これを誤診する傾向があります。
混乱する前に考える
「私はあなたの人々について知りませんが…」
考えるべき最終的な手段として、誤った最適化のアイデアを、プロジェクトや会社自体、さらには経済のセクターなど、はるかに広い視野にどのように適用できるかを検討してください。
テクノロジーがその日を救うこと、そしてそれを実現するヒーローになることができると考えたくなることはわかっています。
さらに、私たちがそれをしなければ、他の誰かがそうするでしょう。
しかし、最善の意図にもかかわらず、権力は腐敗することを忘れないでください。 ここでは特定の記事にリンクしませんが、もしあなたが何も見たことがなければ、経済を混乱させることのより広い影響と、これが最終的に誰に役立つかについて調べる価値があります。 最適化を通じて世界を救おうとすることの副作用のいくつかに驚かれるかもしれません。
追記
オプティマス、何か気づきましたか? 私があなたにオプティマスと呼んだのは、最初と最後でした。 記事全体を通して、あなたはOptimusと呼ばれていませんでした。 正直、忘れてしまいました。 私はあなたをオプティマスと呼ばずに記事全体を書きました。 最後に、私が戻ってテキスト全体にあなたの名前を振りかける必要があることに気付いたとき、私の中の小さな声が言った、それをしないでください。