8

Java のデフォルトの文字列インターンには多くの悪評が寄せられているため、代替手段を探しています。

Java 文字列のインターンに代わる優れた API を提案できますか? 私のアプリケーションは Java 6 を使用しています。私の要件は、主にインターンによる文字列の重複を避けることです。

悪い報道について:

  • 文字列インターンは、ネイティブ メソッドを介して実装されます。また、C の実装では、1k エントリの固定サイズを使用し、多数の文字列のスケーリングが非常に不十分です。
  • Java 6 はインターンされた文字列を Perm gen に格納します。したがって、GC されず、perm gen エラーにつながる可能性があります。これは Java 7 で修正されていることはわかっていますが、Java 7 にアップグレードできません。

なぜインターリングを使用する必要があるのですか?

  • 私のアプリケーションは、さまざまな展開でヒープ サイズが 10 ~ 20G のサーバー アプリです。
  • プロファイリング中に、数十万の文字列が重複していることがわかりました。重複した文字列を保存しないようにすることで、メモリ使用量を大幅に改善できます。
  • メモリは私たちにとってボトルネックであったため、時期尚早の最適化を行うのではなく、メモリをターゲットにしています。
4

1 に答える 1

12

文字列インターンは、ネイティブメソッドを介して実装されます。また、Cの実装では、固定サイズの1kエントリが使用され、多数の文字列に対してはスケーリングが非常に不十分です。

何千ものストリングに対してはスケーリングが不十分です。

Java 6は、インターンされた文字列をPermgenに格納します。したがって、GCされません

perm genがクリーンアップされるとクリーンアップされますが、これは頻繁ではありませんが、このスペースを増やさないと、このスペースの最大値に達する可能性があります。

私のアプリケーションは、さまざまな展開用のヒープサイズが10〜20Gのサーバーアプリです。

オフヒープメモリの使用を検討することをお勧めします。1つのアプリケーションに500GBのオフヒープメモリと約1GBのヒープがあります。すべての場合に役立つわけではありませんが、検討する価値があります。

プロファイリング中に、数十万の文字列が重複していることがわかりました。重複した文字列の保存を回避することで、メモリ使用量を大幅に改善できます。

このために、私は文字列の単純な配列を使用しました。これは非常に軽量で、保存されている文字列の上限を簡単に制御できます。


これが一般的なインターナーの例です。

class Interner<T> {
    private final T[] cache;

    @SuppressWarnings("unchecked")
    public Interner(int primeSize) {
        cache = (T[]) new Object[primeSize];
    }

    public T intern(T t) {
        int hash = Math.abs(t.hashCode() % cache.length);
        T t2 = cache[hash];
        if (t2 != null && t.equals(t2))
            return t2;
        cache[hash] = t;
        return t;
    }
}

このキャッシュの興味深い特性は、スレッドセーフでないことは問題ではないということです。

速度を上げるために、2の累乗のサイズとビットマスクを使用できますが、より複雑で、hashCodesの計算方法によってはうまく機能しない場合があります。

于 2012-10-09T06:12:26.307 に答える