Java字符串实习的替代方案

时间:2012-10-09 04:44:48

标签: java string memory string-interning

由于Java的默认字符串实习有很多坏消息,我正在寻找替代方案。

你能建议一个API,它是Java字符串实习的一个很好的替代品吗?我的应用程序使用Java 6.我的要求主要是通过实习来避免重复的字符串。

关于坏消息:

  • 字符串实习生是通过本机方法实现的。并且C实现使用大约1k条目的固定大小,并且对于大量字符串而言非常差。
  • Java 6在Perm gen中存储实习字符串。因此不是GC'd并且可能导致烫发错误。我知道这在java 7中已修复,但我无法升级到java 7.

为什么我需要使用intering?

  • 我的应用程序是一个服务器应用程序,堆大小为10-20G,适用于不同的部署。
  • 在分析期间,我们已经发现数千个字符串的数据是重复的,我们可以通过避免存储重复的字符串来显着提高内存使用率。
  • 内存一直是我们的瓶颈,因此我们正在瞄准它,而不是做任何过早的优化。

1 个答案:

答案 0 :(得分:11)

  

字符串实习生是通过本机方法实现的。并且C实现使用大约1k条目的固定大小,并且对于大量字符串的扩展非常差。

对于数千个字符串,它的扩展性很差。

  

Java 6在Perm gen中存储实习字符串。因此不是GC'd

当清理烫发时,它会被清理掉,但这并不常见,但如果你不增加烫发,则可能意味着你达到了这个空间的最大值。

  

我的应用程序是一个服务器应用程序,堆大小为10-20G,适用于不同的部署。

我建议你考虑使用off heap memory。我在off heap内存中有500 GB,在一个应用程序中有大约1 GB的堆。它并非在所有情况下都有用,但值得考虑。

  

在分析期间,我们已经发现数千个字符串的数据是重复的,我们可以通过避免存储重复的字符串来显着提高内存使用率。

为此,我使用了一个简单的String数组。这是非常轻的重量,您可以轻松控制存储的字符串的上限。


这是一个通用内部的例子。

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的计算方式。