我已经看到许多描述 String intern()'ing 如何工作的原始示例,但我还没有看到可以从中受益的真实用例。
我能想到的唯一情况是拥有一个接收大量请求的 Web 服务,由于严格的模式,每个请求在性质上都非常相似。在这种情况下,通过对请求字段名称进行实习(),可以显着减少内存消耗。
谁能提供一个在生产环境中使用 intern() 并取得巨大成功的例子?也许是流行的开源产品中的一个例子?
编辑:我指的是手动实习,而不是字符串文字的保证实习等。
我已经看到许多描述 String intern()'ing 如何工作的原始示例,但我还没有看到可以从中受益的真实用例。
我能想到的唯一情况是拥有一个接收大量请求的 Web 服务,由于严格的模式,每个请求在性质上都非常相似。在这种情况下,通过对请求字段名称进行实习(),可以显着减少内存消耗。
谁能提供一个在生产环境中使用 intern() 并取得巨大成功的例子?也许是流行的开源产品中的一个例子?
编辑:我指的是手动实习,而不是字符串文字的保证实习等。
如果您的N
字符串只能采用K
不同的值,并且N
远远超过K
. 现在,N
您不再将字符串存储在内存中,而是最多存储K
.
例如,您可能有一个ID
由 5 位数字组成的类型。因此,只能有10^5
不同的值。假设您现在正在解析一个大型文档,其中包含许多对ID
值的引用/交叉引用。假设该文档10^9
总共有参考文献(显然某些参考文献在文档的其他部分重复)。
所以在这种情况下N = 10^9
。K = 10^5
如果您没有实习字符串,您将把10^9
字符串存储在内存中,其中很多字符串都在内存中equals
(通过Pigeonhole 原则)。如果您在解析文档时获得intern()
了ID
字符串,并且您没有保留对从文档中读取的非内部字符串的任何引用(因此它们可以被垃圾收集),那么您将永远不需要存储超过10^5
字符串在记忆中。
不是一个完整的答案,而是额外的思考(在这里找到):
因此,在这种情况下,主要的好处是使用
==
操作符处理内部化字符串比使用equals()
方法 [for not internalized Strings] 快得多。因此,intern()
如果您要比较字符串超过一到三次,请使用该方法。
我们有一个生产系统,可以一次处理数百万条数据,其中许多具有字符串字段。我们应该一直在实习字符串,但有一个错误意味着我们没有。通过修复错误,我们避免了进行非常昂贵(至少 6 位数,可能 7 位数)的服务器升级。
实习有益的示例涉及大量字符串,其中:
典型示例包括将文本拆分/解析为符号(单词、标识符、URI),然后将这些符号附加到长期存在的数据结构中。XML 处理、编程语言编译和 RDF / OWL 三重存储作为实习可能有益的应用程序一时浮现在脑海中。
但是实习也不是没有问题,尤其是如果上面的假设是不正确的:
最后,通过增加需要跟踪和复制的对象数量以及需要处理的弱引用数量,实习可能会增加 GC 开销。这种开销的增加必须与有效实习导致的 GC 开销的减少相平衡。
永远不要对用户提供的数据使用实习生,因为这会导致拒绝服务攻击(因为实习生()化的字符串永远不会被释放)。您可以对用户提供的字符串进行验证,但是您又完成了 intern() 所需的大部分工作。