【问题标题】:Alternatives to Java string interningJava 字符串实习的替代方案
【发布时间】:2012-09-29 08:46:52
【问题描述】:

由于 Java 的默认字符串实习受到了很多负面报道,我正在寻找替代方案。

你能推荐一个 API 来替代 Java 字符串实习吗?我的应用程序使用 Java 6。我的要求主要是通过实习避免重复字符串。

关于负面新闻:

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

为什么我需要使用 intering?

  • 我的应用程序是一个服务器应用程序,堆大小为 10-20G,用于不同的部署。
  • 在分析期间,我们发现数十万个字符串是重复的,我们可以通过避免存储重复的字符串来显着提高内存使用率。
  • 内存一直是我们的瓶颈,因此我们将其作为目标,而不是进行任何过早的优化。

【问题讨论】:

  • 我的一部分尊重你发布的要求,但如果“坏消息”足以让你避免它们,那么我真的不得不问你是如何分析你的应用程序的(如果有的话)确定 Java 字符串不适合。
  • 您是否注意到您的应用程序中存在与这些问题相关的问题?如果没有,我不会担心。
  • @Keppil 我的应用程序有数十万个重复的字符串。所以实习对我来说是必须的。
  • @pst 希望我已经回答了你的问题。我假设您指的是 Map 而不是 Set。我需要一些线程安全的东西,一旦不再引用它们就会对字符串进行 GC。类似并发弱哈希映射。
  • @ManojGumber stackoverflow.com/questions/8853515/… (impl with Map) , stackoverflow.com/questions/3972841/… (提到 Guava Interner)

标签: java string memory string-interning


【解决方案1】:

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

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

Java 6 在 Perm gen 中存储实习字符串。因此不会被 GC 处理

它会在 perm gen 被清理时被清理,这并不经常,但如果你不增加它,这可能意味着你达到了这个空间的最大值。

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

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

在分析过程中,我们发现数十万个字符串是重复的,我们可以通过避免存储重复字符串来显着提高内存使用率。

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


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

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 的幂和位掩码,但它更复杂,并且可能无法很好地工作,具体取决于您的 hashCode 的计算方式。

【讨论】:

  • 对于字符串数组方法,它只是一个无序集合吗?
  • @peter Lawrey 它将如何处理碰撞。即当两个具有不同哈希码的字符串指向相同的缓存索引时?是否有假设您将 Interner 的大小设置为您期望不同字符串的数量?
  • 如果发生冲突,它将替换那里的值。大小需要比您可能认为最佳的字符串数量大 2-3 倍,因为它不会非常聪明地处理冲突。 BTW 甚至 HashMap 将是条目数的 1.4 到 2.8 倍。您可以使用primes.utm.edu/curios 找到任何大小的“有趣”素数。
猜你喜欢
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 2018-11-04
  • 1970-01-01
  • 2012-05-21
相关资源
最近更新 更多