在Java中实现所有字符串的性能影响是什么?

时间:2017-11-12 04:26:34

标签: java string performance

我正在处理一个交易处理应用程序,我必须处理很多字符串。其中一些字符串是非重复的,例如商品ID,而其他字符串经常重复,例如产品ID。

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

我的问题是,我是否可能会因此移动无意中降低性能?

1 个答案:

答案 0 :(得分:3)

重复编写常用字符串通常是节省内存的好主意 但绝不要将String.intern用于重复数据删除!

  • String.intern是一种原生方法;每次通话都会遇到额外的JNI overhead
  • 它吹掉了所有JVM部分共享的内部哈希表(例如,类加载)。
  • 字符串表的默认容量不够大,存储桶数量不变。
  • 可能会增加GC暂停,因为JVM会扫描此内部哈希表,并可能在世界停止阶段重新对其进行重新处理。
  • this presentation
  • 中的更多详情

常规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