本番環境でのJava EqualsとHashcodeパフォーマンスのデバッグ

この記事では、equalsメソッドとハッシュコードのパフォーマンスメトリックについて多くのことを書きました。これらのメソッドのパフォーマンスの問題につながる可能性のあるニュアンスはたくさんあります。問題は、それらのいくつかがうまく隠されている可能性があるということです。

主要な問題を要約すると、ハッシュコードメソッドはJavaコレクションAPIの中心です。具体的には、ハッシュテーブル(具体的にはMapインターフェイスハッシュテーブル)のパフォーマンスを使用します。同じことがequalsメソッドにも当てはまります。文字列オブジェクトやプリミティブよりも複雑なものがある場合、オーバーヘッドはすぐに大きくなる可能性があります。

しかし、主な問題は微妙な振る舞いです。この記事に記載されている例は、JavaSEURLクラスの例です。そのクラスのAPIは、これらの個別のオブジェクトの次の比較がtrueと評価されることを指定しています。

new URL("http://127.0.0.1/").equals(new URL("http://localhost/")); 

new URL("http://127.0.0.1/").hashcode() == new URL("http://localhost/").hashcode();

これは仕様のバグです。これはすべてのドメインに適用されるため、ハッシュまたは等しいを実行するにはルックアップが必要であることに注意してください。それは非常に高くつく可能性があります。

ヒント: equals / hashcodeのパフォーマンスは、マップやその他のハッシュベースのコレクションなどのキー値コンテナーでの使用に非常に効率的である必要があります

これらの方法には多くの落とし穴があります。それらのいくつかは、大規模にのみ明らかです。たとえば、友人がオブジェクトを比較し、潜在的な値のリストに外部依存する方法を教えてくれました。これはローカルでは優れたパフォーマンスを発揮しましたが、リストに要素が多い本番環境ではゆっくりと実行されました。

ハッシュ関数の生成が遅いかどうかをどのように判断できますか?

それがハッシュ関数のせいであるとどうやって知るのですか?

性能測定

ほとんどの目的と目的では、問題がequalsメソッドまたはハッシュコードにあることはわかりません。問題を絞り込む必要があります。サーバープロセスは予想よりも時間がかかり、APMに表示される可能性があります。

APMに表示されるのは、Webサービスのパフォーマンスが遅いことです。Lightrunが提供するメトリクスツールを使用して、それを絞り込むことができます。

注:先に進む前に、Lightrunの基本に精通していて、インストールされていることを前提としています。そうでない場合は、この紹介をチェックしてください。

指標メニュー

Lightrunには、いくつかのメトリックタイプを設定する機能が含まれています。

  • 特定のコード行に到達した回数をカウントするカウンター
  • 特定のコードブロックのパフォーマンスを測定する時間測定(tictoc)
  • メソッド期間–完全なメソッドのtictocと同じ
  • カスタムメトリック–カスタム式に基づいて測定

すべてのメトリックで条件を使用できることに注意してください。パフォーマンスのオーバーヘッドが特定のユーザーに影響を与える場合は、その特定のユーザーのみに測定を制限できます。

これで、これらのツールを使用してパフォーマンスの問題を絞り込み、根本的な原因を見つけることができます。たとえば、ここでは、メソッドのこれら2つの行に問題があるかどうかを確認できます。

TicTocの追加

このtictocを追加すると、次のような定期的なプリントアウトが提供されます。

INFO: 13 Feb 2022, 14:50:06 TicToc Stats::
{
  "VetListBlock" : {"breakpointId" : "fc27d745-b394-400e-83ee-70d7644272f3","count" : 33,"max" : 32,"mean" : 4.971277332041485,"min" : 1,"name" : "VetListBlock","stddev" : 5.908043099655046,"timestamp" : 1644756606939  }
}

これらのプリントアウトを確認して、これらの行によって発生するオーバーヘッドの感覚をつかむことができます。カウンターを使用して、メソッドを呼び出す頻度を確認することもできます。

注:これらの結果をPrometheus / Grafanaにパイプして視覚化を向上させることができますが、そのためには、このチュートリアルの範囲外の構成が必要です。

コレクションまたはマップがアプリケーションの主なパフォーマンスの低下として見られる場合は、厄介なハッシュコードまたはequalsメソッドに問題がある可能性があります。この時点で、メソッド自体のメトリックを使用して、そのオーバーヘッドを測定できます。

これは、これらをローカルでデバッグする方法と非常によく似ています。疑わしい領域を測定で囲み、テストを再実行します。残念ながら、このアプローチはアプリの再コンパイル/デプロイが必要なため、時間がかかります。また、本番環境では実用的ではありません。このアプローチを使用すると、すべての「疑わしい」領域をすばやく確認し、それらをすべてすばやく絞り込むことができます。

さらに、タグ機能を使用して、一連のサーバーでこれを行うことができます。このようにして、サーバーをスケーリングするときに測定値をスケーリングできます。

スレッドセーフの確認

可変オブジェクトは、デバッグ中に複数のスレッドから変更できます。これにより、パフォーマンスの問題と思われる問題が発生する可能性があります。シングルスレッドアクセスがあることを確認することで、クリティカルセクションの同期を減らすこともできます。

たとえば、キー値ストアでは、別のスレッドがキーを変更すると、ストアが破損する可能性があります。

これを行う最も簡単な方法は、現在のスレッドが次の条件を使用して現在のスレッドをログに記録することです{Thread.currentThread().getName()}

デバッグスレッドの問題

問題は、このような状態が、追跡が難しい出力をトリガーする可能性があることです。何百ものプリントアウトが表示される可能性があります。したがって、スレッドの名前を見つけたら、条件を追加できます。

!Thread.currentThread().getName().equals("threadName")

これは、異なるスレッドからのアクセスのみをログに記録します。これは、以前の投稿でここで説明したことです。

TL; DR

JavaSEのequalsメソッドとhashcodeメソッドのパフォーマンスメトリックは非常に重要です。これらは、特に呼び出しに関連するキー値において、JavaコレクションAPIに広範囲に影響を及ぼします。オブジェクトはこれを効率的に実装する必要がありますが、多くの場合、障害のあるJavaクラスを特定するのは困難です。

Lightrunメトリックを使用して、本番環境で任意のメソッドの時間を計測できます。「実世界」の環境でクラスのパフォーマンスを測定することが重要です。これは、ローカルのテストケースとは異なる場合があります。オブジェクトは、実稼働規模のデータとは根本的に異なる動作をする可能性があり、クラスへの小さな変更が大きな違いを生む可能性があります。

ハッシュのオーバーヘッドを絞り込み、ログを使用してスレッドの問題を特定し、カウンターを使用してAPIの使用状況を特定できます。

このストーリーは、もともとhttps://talktotheduck.dev/debugging-java-equals-and-hashcode-performance-in-productionで公開されました

 #hashcode  #api #equality #java #csharp 

What is GEEK

Buddha Community

本番環境でのJava EqualsとHashcodeパフォーマンスのデバッグ

本番環境でのJava EqualsとHashcodeパフォーマンスのデバッグ

この記事では、equalsメソッドとハッシュコードのパフォーマンスメトリックについて多くのことを書きました。これらのメソッドのパフォーマンスの問題につながる可能性のあるニュアンスはたくさんあります。問題は、それらのいくつかがうまく隠されている可能性があるということです。

主要な問題を要約すると、ハッシュコードメソッドはJavaコレクションAPIの中心です。具体的には、ハッシュテーブル(具体的にはMapインターフェイスハッシュテーブル)のパフォーマンスを使用します。同じことがequalsメソッドにも当てはまります。文字列オブジェクトやプリミティブよりも複雑なものがある場合、オーバーヘッドはすぐに大きくなる可能性があります。

しかし、主な問題は微妙な振る舞いです。この記事に記載されている例は、JavaSEURLクラスの例です。そのクラスのAPIは、これらの個別のオブジェクトの次の比較がtrueと評価されることを指定しています。

new URL("http://127.0.0.1/").equals(new URL("http://localhost/")); 

new URL("http://127.0.0.1/").hashcode() == new URL("http://localhost/").hashcode();

これは仕様のバグです。これはすべてのドメインに適用されるため、ハッシュまたは等しいを実行するにはルックアップが必要であることに注意してください。それは非常に高くつく可能性があります。

ヒント: equals / hashcodeのパフォーマンスは、マップやその他のハッシュベースのコレクションなどのキー値コンテナーでの使用に非常に効率的である必要があります

これらの方法には多くの落とし穴があります。それらのいくつかは、大規模にのみ明らかです。たとえば、友人がオブジェクトを比較し、潜在的な値のリストに外部依存する方法を教えてくれました。これはローカルでは優れたパフォーマンスを発揮しましたが、リストに要素が多い本番環境ではゆっくりと実行されました。

ハッシュ関数の生成が遅いかどうかをどのように判断できますか?

それがハッシュ関数のせいであるとどうやって知るのですか?

性能測定

ほとんどの目的と目的では、問題がequalsメソッドまたはハッシュコードにあることはわかりません。問題を絞り込む必要があります。サーバープロセスは予想よりも時間がかかり、APMに表示される可能性があります。

APMに表示されるのは、Webサービスのパフォーマンスが遅いことです。Lightrunが提供するメトリクスツールを使用して、それを絞り込むことができます。

注:先に進む前に、Lightrunの基本に精通していて、インストールされていることを前提としています。そうでない場合は、この紹介をチェックしてください。

指標メニュー

Lightrunには、いくつかのメトリックタイプを設定する機能が含まれています。

  • 特定のコード行に到達した回数をカウントするカウンター
  • 特定のコードブロックのパフォーマンスを測定する時間測定(tictoc)
  • メソッド期間–完全なメソッドのtictocと同じ
  • カスタムメトリック–カスタム式に基づいて測定

すべてのメトリックで条件を使用できることに注意してください。パフォーマンスのオーバーヘッドが特定のユーザーに影響を与える場合は、その特定のユーザーのみに測定を制限できます。

これで、これらのツールを使用してパフォーマンスの問題を絞り込み、根本的な原因を見つけることができます。たとえば、ここでは、メソッドのこれら2つの行に問題があるかどうかを確認できます。

TicTocの追加

このtictocを追加すると、次のような定期的なプリントアウトが提供されます。

INFO: 13 Feb 2022, 14:50:06 TicToc Stats::
{
  "VetListBlock" : {"breakpointId" : "fc27d745-b394-400e-83ee-70d7644272f3","count" : 33,"max" : 32,"mean" : 4.971277332041485,"min" : 1,"name" : "VetListBlock","stddev" : 5.908043099655046,"timestamp" : 1644756606939  }
}

これらのプリントアウトを確認して、これらの行によって発生するオーバーヘッドの感覚をつかむことができます。カウンターを使用して、メソッドを呼び出す頻度を確認することもできます。

注:これらの結果をPrometheus / Grafanaにパイプして視覚化を向上させることができますが、そのためには、このチュートリアルの範囲外の構成が必要です。

コレクションまたはマップがアプリケーションの主なパフォーマンスの低下として見られる場合は、厄介なハッシュコードまたはequalsメソッドに問題がある可能性があります。この時点で、メソッド自体のメトリックを使用して、そのオーバーヘッドを測定できます。

これは、これらをローカルでデバッグする方法と非常によく似ています。疑わしい領域を測定で囲み、テストを再実行します。残念ながら、このアプローチはアプリの再コンパイル/デプロイが必要なため、時間がかかります。また、本番環境では実用的ではありません。このアプローチを使用すると、すべての「疑わしい」領域をすばやく確認し、それらをすべてすばやく絞り込むことができます。

さらに、タグ機能を使用して、一連のサーバーでこれを行うことができます。このようにして、サーバーをスケーリングするときに測定値をスケーリングできます。

スレッドセーフの確認

可変オブジェクトは、デバッグ中に複数のスレッドから変更できます。これにより、パフォーマンスの問題と思われる問題が発生する可能性があります。シングルスレッドアクセスがあることを確認することで、クリティカルセクションの同期を減らすこともできます。

たとえば、キー値ストアでは、別のスレッドがキーを変更すると、ストアが破損する可能性があります。

これを行う最も簡単な方法は、現在のスレッドが次の条件を使用して現在のスレッドをログに記録することです{Thread.currentThread().getName()}

デバッグスレッドの問題

問題は、このような状態が、追跡が難しい出力をトリガーする可能性があることです。何百ものプリントアウトが表示される可能性があります。したがって、スレッドの名前を見つけたら、条件を追加できます。

!Thread.currentThread().getName().equals("threadName")

これは、異なるスレッドからのアクセスのみをログに記録します。これは、以前の投稿でここで説明したことです。

TL; DR

JavaSEのequalsメソッドとhashcodeメソッドのパフォーマンスメトリックは非常に重要です。これらは、特に呼び出しに関連するキー値において、JavaコレクションAPIに広範囲に影響を及ぼします。オブジェクトはこれを効率的に実装する必要がありますが、多くの場合、障害のあるJavaクラスを特定するのは困難です。

Lightrunメトリックを使用して、本番環境で任意のメソッドの時間を計測できます。「実世界」の環境でクラスのパフォーマンスを測定することが重要です。これは、ローカルのテストケースとは異なる場合があります。オブジェクトは、実稼働規模のデータとは根本的に異なる動作をする可能性があり、クラスへの小さな変更が大きな違いを生む可能性があります。

ハッシュのオーバーヘッドを絞り込み、ログを使用してスレッドの問題を特定し、カウンターを使用してAPIの使用状況を特定できます。

このストーリーは、もともとhttps://talktotheduck.dev/debugging-java-equals-and-hashcode-performance-in-productionで公開されました

 #hashcode  #api #equality #java #csharp