Tur*_*rac 1 java concurrency performance
我正在研究 String.intern() ,这种方法有性能损失。我将 String.intern() 与 ConcurrentHashMap.putIfAbsent(s,s) 与 Microbenchmark 进行了比较。使用Java1.8.0_212,Ubuntu 18.04.2 LTS
\n\n@Param({"1", "100", "10000", "1000000"})\nprivate int size;\n\nprivate StringIntern stringIntern;\nprivate ConcurrentHashMapIntern concurrentHashMapIntern;\n\n@Setup\npublic void setup(){\n stringIntern = new StringIntern();\n concurrentHashMapIntern = new ConcurrentHashMapIntern();\n}\npublic static class StringIntern{\n public String intern(String s){\n return s.intern();\n }\n}\npublic static class ConcurrentHashMapIntern{\n private final Map<String, String> map;\n\n public ConcurrentHashMapIntern(){\n map= new ConcurrentHashMap<>();\n }\n public String intern(String s){\n String existString = map.putIfAbsent(s, s);\n return (existString == null) ? s : existString;\n }\n}\n\n@Benchmark\npublic void intern(Blackhole blackhole){\n for(int count =0; count<size; count ++){\n blackhole.consume(stringIntern.intern("Example "+count));\n }\n}\n@Benchmark\npublic void concurrentHashMapIntern(Blackhole blackhole){\n for(int count =0; count<size; count++){\n blackhole.consume(concurrentHashMapIntern.intern("Example " +count));\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n结果符合预期。搜索字符串时,ConcurrentHashMap 比 String.intern() 更快。
\n\nBenchmark (size) Mode Cnt Score Error Units\nMyBenchmark.concurrentHashMapIntern 1 avgt 5 0.056 \xc2\xb1 0.007 us/op\nMyBenchmark.concurrentHashMapIntern 100 avgt 5 6.094 \xc2\xb1 2.359 us/op\nMyBenchmark.concurrentHashMapIntern 10000 avgt 5 787.802 \xc2\xb1 264.179 us/op\nMyBenchmark.concurrentHashMapIntern 1000000 avgt 5 136504.010 \xc2\xb1 17872.866 us/op\nMyBenchmark.intern 1 avgt 5 0.129 \xc2\xb1 0.007 us/op\nMyBenchmark.intern 100 avgt 5 13.700 \xc2\xb1 2.404 us/op\nMyBenchmark.intern 10000 avgt 5 1618.514 \xc2\xb1 460.563 us/op\nMyBenchmark.intern 1000000 avgt 5 1027915.854 \xc2\xb1 638910.023 us/op\nRun Code Online (Sandbox Code Playgroud)\n\nString.intern() 比 ConcurrentHashMap 慢,因为 String.intern() 是原生 HashTable 实现。然后,阅读有关 HashTable 的javadoc,该文档说明:
\n\n\n\n\n如果不需要线程安全的实现,建议使用HashMap代替Hashtable。如果需要线程安全的高并发实现,那么建议使用ConcurrentHashMap代替Hashtable。
\n
这是非常令人困惑的情况。它推荐ConcurrentHashMap,但它使用HashTable虽然性能有所损失。有谁知道为什么使用 ConcurrentHashMap 的本机 HashTable 实现实例?
\n这里发生了很多事情:
您的基准测试有非常大的误差线。重复计数可能太小。这使得结果值得怀疑。
看起来您的基准测试并没有在每次运行1之后重置“interned string”缓存。因此,这意味着缓存正在增长,并且每次重复都会以不同的条件开始。这可以解释误差线......
您的ConcurrentHashMap功能在功能上不等同于String::intern. 后者使用Reference对象的本机等效项来确保可以对内部字符串进行垃圾收集。你的ConcurrentHashMap实现没有。为什么这很重要?
ConcurrentHashMap内存泄漏严重。String.intern() 比 ConcurrentHashMap 慢,因为 String.intern() 是原生 HashTable 实现。
不。真正的原因是本机实现的做法不同:
intern) 字符串池使用以本机代码实现的自定义哈希表。请注意,这些内容在不同的 Java 版本中差异很大。
这是非常令人困惑的情况。它推荐ConcurrentHashMap,但它使用HashTable虽然性能有所损失。
现在你正在谈论一个不同的场景,它与你正在做的事情无关。
请注意,String::intern不使用HashTableor HashMap;往上看。
您找到的引用是关于如何从哈希表获得良好的并发性能。您的基准是(AFAIK)单线程。对于串行用例,HashMap将提供比其他用例更好的性能。
有谁知道为什么使用本机
HashTable实现实例ConcurrentHashMap?
它不使用哈希表;往上看。HashTable没有或HashMap或 的原因有很多ConcurrentHashMap:
Reference非常大。最后,请小心,不要在这里关注错误的问题。如果您因为实习是应用程序的瓶颈而尝试优化实习,则另一种策略是根本不实习。在实践中,它很少节省内存(特别是与G1GC的字符串去重相比)并且很少提高字符串处理性能。
总之:
String::intern不仅仅(甚至主要)针对速度进行优化。1 - 在本机intern情况下,我认为这是不可能的。
2 - 常规堆中的 Java 内存泄漏会影响长期 GC 性能,因为保留的对象需要由 GC 重复标记和复制。也可能有副作用。
| 归档时间: |
|
| 查看次数: |
570 次 |
| 最近记录: |