インタビュー: Java パフォーマンスの最適化にどのような方法が利用できるか知っていますか?

リリース: 2023-08-16 16:49:14
転載
794 人が閲覧しました

2 日前、グループの友人が私とチャットしに来ました。インタビュー中に、パフォーマンス最適化手法にどう対応するか尋ねられました。今日は話しましょう。 この記事では主に理論分析に焦点を当てていますが、Java のパフォーマンス最適化全体に従うことができるルールを見てみましょう。

この記事は理論に焦点を当てています。 実践に関しては、後続の記事でより多くの事例を使用して、この記事の知識ポイントを洗練させます。繰り返し考えたりまとめたりするのに適しています。

概要 パフォーマンスの最適化は、最適化カテゴリに応じてビジネスの最適化と技術の最適化に分類されます。業務最適化の効果も非常に大きいですが、それは製品と経営の範疇に属します。プログラマーとして、私たちが日常業務で直面する最適化手法は、主に、確立された最適化目標を達成するための一連の技術的手段によるものです。この一連の技術的手段は、次の 7 つのカテゴリに大まかに要約できます。

インタビュー: Java パフォーマンスの最適化にどのような方法が利用できるか知っていますか? ご覧のとおり、最適化手法はコンピューティング リソースとストレージ リソースの計画に焦点を当てています。最適化手法で空間を時間を交換する方法はたくさんありますが、複雑さや空間の問題を考慮せずに計算速度だけを考慮することはお勧めできません。私たちがしなければならないのは、パフォーマンスを考慮しながら最適なリソース使用率を達成することです。

次に、これら 7 つの最適化の方向性を簡単に紹介します。この記事の目的は、総合スコアの概念と理論的基礎を全体的に理解していただくことです。

再利用最適化 コードを作成すると、抽出できる重複コードが多数あることがわかります。それをパブリックメソッドにします。こうすることで、次回使用するときに再度書き込む必要がなくなります。

このアイデアは再利用です。上記の説明はコーディング ロジックの最適化ですが、データ アクセスについても同様の再利用状況が発生します。生活でもコーディングでも、常に同じことが繰り返されるため、再利用がなければ、仕事も生活もさらに疲れてしまいます。

ソフトウェア システムでは、データの再利用というと、最初にバッファリングとキャッシュが思い浮かびます。この 2 つの言葉の違いに注意してください。意味が全く異なるため、混同しやすい学生も多いです。簡単に説明します。

バッファ (バッファ) は、データを一時的に保存し、バッチで転送または書き込みするために一般的に使用されます。シーケンシャル方式は主に、異なるデバイス間の頻繁で遅いランダム書き込みを軽減するために使用され、バッファリングは主に書き込み操作を対象としています。

キャッシュ(Cache)は、読み出したデータを再利用する際によく使われる手法で、比較的高速な領域にキャッシュすることで、主に読み出し動作を対象としています。

同様に、Java で頻繁に使用されるデータベース接続プール、スレッド プールなどのオブジェクトのプーリング操作です。これらのオブジェクトは作成・破棄コストが比較的高いため、使用後も一時的に保管しておくことで、次回使用する際に再度初期化という手間のかかる作業を行う必要がなくなります。

#計算の最適化

並列実行

現在の CPU は非常に急速に発展しており、ほとんどのハードウェアはマルチコアです。特定のタスクの実行を高速化したい場合、最速かつ最良の解決策は、タスクを並列実行させることです。並列実行には 3 つのモードがあります。

最初のモードはマルチマシンで、負荷分散を使用してトラフィックや大規模な計算を複数の部分に分割し、同時に処理します。たとえば、Hadoop は MapReduce を使用してタスクを分割し、複数のマシンが同時に計算を実行できるようにします。

2 番目のモードは、複数のプロセスを使用することです。例えば、NginxはNIOプログラミングモデルを採用しており、マスターがワーカープロセスを一元管理し、ワーカープロセスが実際のリクエストプロキシを行うことで、ハードウェアの複数のCPUを有効に活用することもできます。

3 番目のモードは、マルチスレッドを使用することです。これは、Java プログラマーが最もよく使用するものです。たとえば、Netty は Reactor プログラミング モデルを使用し、NIO も使用しますが、スレッドベースです。 Boss スレッドはリクエストを受信し、実際のビジネス計算のために対応する Worker スレッドにリクエストをスケジュールするために使用されます。

Golang のような言語には、より軽量なコルーチンがあります コルーチンはスレッドよりも軽量な存在ですが、Java ではまだ成熟していないため、あまり紹介されすぎていますが、本質的には、これはマルチコア アプリケーションにも対応しており、タスクを並行して実行できます。

同期から非同期への変更

計算のもう 1 つの最適化は、同期から非同期への変更です。これには通常、プログラミング モデルの変更が伴います。同期モードでは、成功または失敗の結果が返されるまでリクエストはブロックされます。そのプログラミング モデルは単純ですが、期間内に突然の偏ったトラフィックを処理する場合に特に問題が発生し、リクエストが簡単に失敗する可能性があります。

非同期操作は、水平方向の拡張を簡単にサポートし、瞬間的なプレッシャーを軽減し、リクエストをスムーズに行うことができます。同期リクエストは拳で鉄板を叩くようなもので、非同期リクエストは拳でスポンジを叩くようなものです。このプロセスは想像できると思いますが、後者の方が間違いなく柔軟で、エクスペリエンスがよりユーザーフレンドリーです。

遅延読み込み

最後の 1 つは、いくつかの一般的なデザイン パターンを使用してビジネスを最適化し、エクスペリエンスを向上させることです。たとえば、シングルトン モード、プロキシ モードなどです。たとえば、Swing ウィンドウを描画するときに、より多くの画像を表示したい場合は、最初にプレースホルダーを読み込み、次にバックグラウンド スレッドを通じて必要なリソースをゆっくりと読み込むことができます。これにより、ウィンドウのフリーズを回避できます。

結果セットの最適化

次に、結果セットの最適化について紹介します。より直観的な例を挙げると、XML の表現が非常に優れていることは誰もが知っていますが、なぜまだ JSON が存在するのでしょうか?書きやすいことに加えて、サイズが小さくなり、送信効率と解析効率が高くなったことも重要な理由であり、Google の Protobuf と同様にサイズはさらに小さくなっています。可読性は低下しますが、一部の同時実行性の高いシナリオ (RPC など) では、効率が大幅に向上する可能性があり、これは結果セットの一般的な最適化です。

これは、現在の Web サービスがすべて C/S モードであるためです。サーバーからクライアントにデータを送信する場合、複数のコピーを分散する必要があるため、データ量は急速に増大し、少量のストレージが削減されるたびに、送信パフォーマンスとコストが大幅に増加します。

Nginx と同様に、GZIP 圧縮は通常、送信されるコンテンツをコンパクトに保つ​​ためにオンになります。クライアントは、解凍を容易にするために少量の計算能力のみを必要とします。この操作は分散化されているため、パフォーマンス上のペナルティは固定されています。

この原則を理解すると、結果セットの最適化に関する一般的な考え方がわかり、返されるデータを可能な限りシンプルにする必要があります。クライアントに必要のないフィールドがある場合は、コード内で削除するか、SQL クエリ内で直接削除します。

適時性についてはそれほど高い要件はないが、処理能力については高い要件がある一部の企業向け。バッファーの経験から学び、ネットワーク接続の相互作用を最小限に抑え、バッチ処理を使用して処理速度を向上させる必要があります。

結果セットは 2 回使用される可能性が高いため、キャッシュに追加することもできますが、それでも速度が不足しています。このとき、データ アクセスを高速化するには、インデックスまたは Bitmap ビットマップを使用してデータ収集の処理を最適化する必要があります。

リソース競合の最適化

通常の開発では、多くの共有リソースが関係します。これらの共有リソースには、HashMap などのスタンドアロンのもの、データベース行などの外部ストレージ、特定の Redis キーの Setnx などの単一リソース、トランザクションなどの複数のリソースの調整などがあります。 、分散トランザクションなど。

実際には、ロックに関連するパフォーマンスの問題が数多くあります。私たちのほとんどは、データベースの行ロック、テーブル ロック、Java のさまざまなロックなどを思い浮かべます。 CPU コマンド レベルのロック、JVM 命令レベルのロック、オペレーティング システムの内部ロックなどの下位レベルでは、それらはあらゆる場所に存在すると言えます。

リソースの競合が発生する可能性があるのは同時実行性のみです。つまり、同時に共有リソースを取得できる処理要求は 1 つだけです。リソースの競合を解決する方法はロックです。もう 1 つの例はトランザクションです。これは本質的にロックの一種です。

ロック レベルに応じて、ロックは楽観的ロックと悲観的ロックに分類できます。楽観的ロックの方が確実に効率的です。ロックの種類に応じて、ロックは公正なロックと不公平なロックに分類されます。スケジュールに関しては、いくつかの微妙な違いがあります。

リソースの競合はパフォーマンスに重大な問題を引き起こすため、ロックフリーのキューに関する研究が行われ、パフォーマンスが大幅に向上するでしょう。

アルゴリズムの最適化

アルゴリズムは複雑なビジネスのパフォーマンスを大幅に向上させることができますが、実際のビジネスでは、それは亜種です。ストレージがますます安価になるにつれて、CPU が非常に不足している一部のビジネスでは、処理を高速化するためにスペースを時間と引き換えにすることがよくあります。

アルゴリズムはコード チューニングに属します。これには多くのコーディング スキルが必要であり、ユーザーは使用される言語の API に精通している必要があります。場合によっては、アルゴリズムとデータ構造を柔軟に使用することもコード最適化の重要な部分となります。たとえば、時間の複雑さを軽減するために一般的に使用される方法には、再帰、二分、並べ替え、動的プログラミングなどが含まれます。

優れた実装は、不十分な実装よりもシステムに大きな影響を与えます。たとえば、List の実装として、LinkedList と ArrayList はランダム アクセスのパフォーマンスが数桁異なります。別の例として、CopyOnWriteList はコピーオンライトを使用するため、読み取りが多く書き込みが少ないシナリオでのロックの競合を大幅に減らすことができます。同期をいつ使用するか、またスレッドセーフにするかについては、コーディング機能に対するより高い要件も必要になります。

この部分は日々の業務の中での蓄積に注意が必要ですが、以降の授業ではさらに重要な知識を取り上げ、解説を散りばめていきます。

#効率的な実装

毎日のプログラミングでは、優れた設計コンセプトと優れたパフォーマンスを備えたコンポーネントを使用するようにしてください。たとえば、Netty を使用すると、古い Mina コンポーネントを選択する必要がなくなりました。システムを設計するときは、パフォーマンス要素を考慮して、SOAP のような時間のかかるプロトコルを選択しないでください。別の例として、優れた構文アナライザー (JavaCC の使用など) は正規表現よりもはるかに効率的です。

つまり、テスト分析によってシステムのボトルネック点が見つかった場合は、主要なコンポーネントをより効率的なコンポーネントに置き換える必要があります。この場合、アダプターのパターンが非常に重要です。これが、多くの企業が既存のコンポーネントの上に抽象化レイヤーを追加することを好む理由であり、基礎となるコンポーネントが切り替わっても、上位レイヤーのアプリケーションはそれを認識しません。

JVM の最適化

Java は JVM 仮想マシン上で実行されるため、その機能の多くは JVM によって制限されます。 JVM 仮想マシンを最適化すると、JAVA プログラムのパフォーマンスもある程度向上します。パラメーターが不適切に構成されている場合、OOM などの重大な結果を引き起こす可能性もあります。

現在広く使用されているガベージ コレクターは G1 であり、パラメータ設定が非常に少ないため、メモリを効率的にリサイクルできます。 CMS ガベージ コレクターは Java 14 で削除されました。CMS ガベージ コレクターの GC 時間は制御できないため、可能であれば使用を避ける必要があります。

JVM パフォーマンスのチューニングにはあらゆる側面でのトレードオフが関係しており、多くの場合、ボディ全体に影響を与えるため、あらゆる側面の影響を包括的に考慮する必要があります。したがって、JVM 内の動作原理の一部を理解することが特に重要であり、コードをより深く理解し、より効率的なコードを作成するのに役立ちます。

概要

上記は、コード最適化の 7 つの一般的な方向性です。パフォーマンスの最適化の内容を一般的に理解しています。これら 7 つの主要な方向は、コード最適化の最も重要な方向です。もちろん、パフォーマンスの最適化には、データベースの最適化、オペレーティング システムの最適化、アーキテクチャの最適化などの内容も含まれます。これらは私たちの焦点では​​ありません。次の記事では、概要のみを説明します。概要を紹介します。

以上がインタビュー: Java パフォーマンスの最適化にどのような方法が利用できるか知っていますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:Java后端技术全栈
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!