Java 8の文字列重複排除機能 質問する

Java 8の文字列重複排除機能 質問する

StringJavaでは(他の言語と同様に)文字ごとに2バイト消費するため、大量のメモリを消費します。そのため、Java 8では、文字列の重複排除これは、char 配列が文字列と final の内部にあるという事実を利用しており、JVM がそれらを操作することができます。

読みましたこの例これまでのところ、私はプロの Java コーダーではないので、概念を理解するのに苦労しています。

そこにはこう書いてある。

文字列の複製にはさまざまな戦略が検討されていますが、現在実装されている戦略は次のアプローチに従います。ガベージ コレクターが文字列オブジェクトにアクセスするたびに、文字配列に注目します。ハッシュ値を取得し、配列への弱参照とともに保存します。同じハッシュ コードを持つ別の文字列が見つかると、文字ごとに比較します。これらも一致する場合、1 つの文字列が変更され、2 番目の文字列の文字配列を指します。最初の文字配列は参照されなくなり、ガベージ コレクションの対象になります。

もちろん、このプロセス全体はいくらかのオーバーヘッドをもたらしますが、厳しい制限によって制御されます。たとえば、文字列に重複がしばらく見つからない場合、その文字列はチェックされなくなります。

私の最初の質問は、

このトピックは Java 8 アップデート 20 で最近追加されたため、まだリソースが不足していますString。Java で消費されるメモリを削減するのにどのように役立つか、実用的な例を共有していただける方はいらっしゃいますか?

編集:

上記のリンクには、

同じハッシュコードを持つ別の文字列が見つかるとすぐに、それらを文字ごとに比較します。

2つ目の質問は、

2 つのハッシュ コードStringが同じであれば、それらはStringsすでに同じです。では、2 つのハッシュ コードが同じであることがわかったら、なぜそれらを比較するのcharでしょうか?charString

ベストアンサー1

@assylias の回答は、基本的にそれがどのように機能するかを説明しており、非常に良い回答です。私は文字列重複除去を使用して実稼働アプリケーションをテストし、いくつかの結果を得ました。Web アプリは文字列を頻繁に使用するため、利点はかなり明らかだと思います。

文字列重複排除を有効にするには、次の JVM パラメータを追加する必要があります (少なくとも Java 8u20 が必要です)。

-XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics

最後のはオプションですが、名前の通り、文字列重複除去の統計を表示します。私のものは次のとおりです。

[GC concurrent-string-deduplication, 2893.3K->2672.0B(2890.7K), avg 97.3%, 0.0175148 secs]
   [Last Exec: 0.0175148 secs, Idle: 3.2029081 secs, Blocked: 0/0.0000000 secs]
      [Inspected:           96613]
         [Skipped:              0(  0.0%)]
         [Hashed:           96598(100.0%)]
         [Known:                2(  0.0%)]
         [New:              96611(100.0%)   2893.3K]
      [Deduplicated:        96536( 99.9%)   2890.7K( 99.9%)]
         [Young:                0(  0.0%)      0.0B(  0.0%)]
         [Old:              96536(100.0%)   2890.7K(100.0%)]
   [Total Exec: 452/7.6109490 secs, Idle: 452/776.3032184 secs, Blocked: 11/0.0258406 secs]
      [Inspected:        27108398]
         [Skipped:              0(  0.0%)]
         [Hashed:        26828486( 99.0%)]
         [Known:            19025(  0.1%)]
         [New:           27089373( 99.9%)    823.9M]
      [Deduplicated:     26853964( 99.1%)    801.6M( 97.3%)]
         [Young:             4732(  0.0%)    171.3K(  0.0%)]
         [Old:           26849232(100.0%)    801.4M(100.0%)]
   [Table]
      [Memory Usage: 2834.7K]
      [Size: 65536, Min: 1024, Max: 16777216]
      [Entries: 98687, Load: 150.6%, Cached: 415, Added: 252375, Removed: 153688]
      [Resize Count: 6, Shrink Threshold: 43690(66.7%), Grow Threshold: 131072(200.0%)]
      [Rehash Count: 0, Rehash Threshold: 120, Hash Seed: 0x0]
      [Age Threshold: 3]
   [Queue]
      [Dropped: 0]

これらはアプリを10分間実行した後の結果です。ご覧のとおり、文字列の重複排除が実行されました。452時間と「重複排除」801.6MB文字列。文字列重複排除の検査27 000 000文字列。Java 7の標準並列GCとJava 8u20のG1 GCと文字列重複排除を有効にした場合のメモリ消費量を比較すると、ヒープは約50%:

Java 7 並列 GC

Java 7 並列 GC

文字列重複排除機能を備えた Java 8 G1 GC

文字列重複排除機能を備えた Java 8 G1 GC

おすすめ記事