通常、メモリを節約するには、一般的な文字列を重複排除することをお勧めします。
重複排除にはString.intern
を使用しないでください。
String.intern
はネイティブメソッドです。各コールにはさらにJNI overheadが発生します。
- すべてのJVMパート間で共有される内部ハッシュテーブルを吹き飛ばします(クラスローディングなど)。
- 文字列テーブルの既定の容量が十分ではなく、バケット数が一定です。
- JVMがこの内部ハッシュテーブルをスキャンし、おそらく世界の段階で再ハッシュするので、GCの一時停止が増加する可能性があります。
- 詳細はthis presentationです。
普通のHashMap
またはConcurrentHashMap
は、この作業のためにはるかに優れています。
次のベンチマークは、1Mの文字列のセットに[Concurrent]HashMap.putIfAbsent
にString.intern
のパフォーマンスを比較しています
@State(Scope.Benchmark)
public class Dedup {
private static final HashMap<String, String> HM = new HashMap<>();
private static final ConcurrentHashMap<String, String> CHM = new ConcurrentHashMap<>();
private static final int SIZE = 1024 * 1024;
private static final String[] STRINGS = new Random(0).ints(SIZE)
.mapToObj(Integer::toString)
.toArray(String[]::new);
int idx;
@Benchmark
public String intern() {
String s = nextString();
return s.intern();
}
@Benchmark
public String hashMap() {
String s = nextString();
String prev = HM.putIfAbsent(s, s);
return prev != null ? prev : s;
}
@Benchmark
public String concurrentHashMap() {
String s = nextString();
String prev = CHM.putIfAbsent(s, s);
return prev != null ? prev : s;
}
private String nextString() {
return STRINGS[++idx & (SIZE - 1)];
}
}
JDK 9の結果(小さい方が良いです):
Benchmark Mode Cnt Score Error Units
Dedup.concurrentHashMap avgt 10 91,208 ± 0,569 ns/op
Dedup.hashMap avgt 10 73,917 ± 0,602 ns/op
Dedup.intern avgt 10 832,700 ± 73,402 ns/op
は、あなたはその時点でいますアプリケーションをチューニングして有効な問題であるとか、これが正当な理由なしにやっていると思っている時期尚早なマイクロ最適化ですか?測定、測定、測定... – Kayaman
私は、インターンは、すべての文字列を入力JSONから抽出してからインターンする必要があるため、解析を高速化できるとは思いません。だから、私は、構文解析が遅くなると思うが、後で助けるかもしれない。バイトとマッチで動作する[JSONパーサ](https://github.com/square/moshi/blob/master/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.java#L158)があります既知の属性名は文字列を生成しません。 – maaartinus