繁体   English   中英

遍历Java中的所有字符串会对性能产生什么影响?

[英]What is the performance impact of interning all strings in Java?

我正在开发一个贸易处理应用程序,其中我必须处理很多字符串。 这些字符串中的一些是非重复的,例如Trade ID,而其他字符串经常重复,例如Product ID。

我正在考虑将所有交易属性作为通用步骤进行解析,同时解析交易消息(JSON)以减少内存使用并加快平等性检查。

我的问题是,此举是否会导致性能下降?

对常见字符串进行重复数据删除通常是节省内存的好主意。
但是请不要使用String.intern进行重复数据删除!

  • String.intern是本机方法; 每个调用都遭受额外的JNI开销
  • 它吹散在所有JVM部分之间共享的内部哈希表(例如,类加载)。
  • 字符串表的默认容量不够大,并且存储桶数是恒定的。
  • 由于JVM会扫描此内部哈希表,并有可能在世界停止阶段重新哈希该哈希表,因此这可能会增加GC暂停时间。
  • 本演示文稿中有更多详细信息。

常规的HashMapConcurrentHashMap可以更好地完成此任务。

以下基准测试将1M字符串集上String.intern[Concurrent]HashMap.putIfAbsent的性能进行了比较:

@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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM