问题标签 [string-interning]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 字符串驻留的搜索成本和文字字符串的声明
两个问题。
当我们声明字面量字符串时,我们会在堆的字符串池中查找是否有相同的字符串。这也是实习(方法实习生
String
)吗?在我看来,每个文字字符串声明都需要二进制搜索或其他东西,因此当n是池中现有字符串的数量时,它至少花费log(n) 。如果池中有很多字符串,则可能成本很高。(也许是搜索成本和内存的权衡?)从这个角度来看,声明 mant 文字字符串可能很危险。 这种搜索成本有多重要以及为什么以这种方式设计java(声明文字字符串时搜索池)。
以下是我所说的了解背景。
字符串是常量;它们的值在创建后无法更改。字符串缓冲区支持可变字符串。因为 String 对象是不可变的,所以它们可以被共享。
http://www.janeg.ca/scjp/lang/strLiteral.html评论:
换句话说,因为编译器知道字符串的原始值一旦创建就不能更改,它可以安全地使用现有数据并避免重复项使内存混乱。
javascript - 常见的 JavaScript 实现是否使用字符串实习?
常见的 JavaScript 引擎,例如 V8 和 WebKit 的 JavaScriptCore,是否对 JavaScript 字符串使用字符串实习?还是他们实际上在内存中保留了多个相同字符串的实例?
java - 我们可以避免在java中插入字符串吗?
我们可以完全禁用字符串的驻留吗?它可能没有真正的帮助,但只是一个想法。我可以认为至少有一点可能会有所帮助,即在 jvm 调整期间,控制 perm gen 的大小。
例如,如果我给出了一个 OSGI 框架,并且任何人都可以添加自己的任意数量的捆绑包,并且每个捆绑包字符串实习可以完全搞砸我的调整参数。(当然我知道我们应该对给定的固定发行版进行调整,但仍然......)
有什么想法吗!!
c# - 获取与 SortedDictionary 中的项目相等的键?
有没有办法从 SortedDictionary 中检索与给定对象相等的键?为了说明,假设我创建了一个字典,它具有相当大的内存,不可变的键类型:
然后稍后,我会做这样的事情:
显然,SortedDictionary 没有“GetKeyEqualTo”方法。但是有什么方法可以达到类似的效果吗?这基本上会产生实习重关键对象的效果,以便可以丢弃相同的实例。我知道我可以使用 SortedList 类通过检索键的索引并随后检索其匹配的对象实例来做到这一点,但 SortedDictionary 的一致插入性能对于我的使用会更好。
如果没有遍历所有字典的键来搜索匹配项,或者编写我自己的 BST 类,有没有办法通过 .NET 的内置集合来实现这一目标?
java - 哪个调试工具可以列出内部化的字符串?
我正在寻找一个可以列出已内化的字符串的调试工具?理想情况下,我想标记并列出在该标记之后添加的字符串。
提前致谢。
java - 关于java的实习生
我的问题是,如果实习生正在使用字符串和具有 SPC(字符串池常量)的字符串,并且实习生概念也使用整数,那么是否有任何整数池常量?如果没有,那么它是如何工作的?
string - 为什么这个字符串的引用计数为 4?(德尔福 2007)
这是一个非常特定于 Delphi 的问题(甚至可能是 Delphi 2007 特定的)。我目前正在为实习字符串编写一个简单的 StringPool 类。作为一个优秀的小程序员,我还添加了单元测试,并发现了一些让我困惑的东西。
这是实习的代码:
没什么特别的:FList 是一个已排序的 TStringList,因此所有代码所做的只是在列表中查找字符串,如果它已经存在,则返回现有字符串。如果它还没有在列表中,它将首先调用 UniqueString 以确保引用计数为 1,然后将其添加到列表中。(我检查了 Result 的引用计数,在添加了两次 'hallo' 之后它是 3,正如预期的那样。)
现在到测试代码:
这会将字符串 'hallo' 添加到字符串池中两次,并检查字符串的引用计数以及 s1 和 s2 确实指向相同的字符串描述符。
每个 CheckEquals 都按预期工作,但最后一个。它失败并出现错误“预期:<3> 但原为:<4>”。
那么,为什么这里的引用计数是 4 呢?我本来期望3:
- s1
- s2
- 另一个在 StringList
这是 Delphi 2007,因此字符串是 AnsiStrings。
哦,是的,函数 StringReferenceCount 实现为:
在调试器中,同样可以评估为:
只是补充一下 Serg 的答案(这似乎是 100% 正确):
如果我更换
和
然后检查 s3(和 s1)的引用计数,它是 3,如预期的那样。正是因为再次将 FPool.Intern(s2) 的结果赋值给 s2(s2 既是函数结果的参数,又是函数结果的目的地)导致了这种现象。Delphi 引入了一个隐藏的字符串变量来分配结果。
另外,如果我将函数更改为过程:
正如预期的那样,引用计数为 3,因为不需要隐藏变量。
如果有人对此 TStringPool 实现感兴趣:它在 MPL 下是开源的,可作为 dzlib 的一部分使用,而 dzlib 又是 dzchart 的一部分:
https://sourceforge.net/p/dzlib/code/HEAD/tree/dzlib/trunk/src/u_dzStringPool.pas
但如上所述:这不完全是火箭科学。;-)
c# - CLR/JVM 是否为所有正在运行的 .net/java 应用程序保留一个实习生池?
以下是MSDN的摘录:
公共语言运行时通过维护一个称为实习池的表来保存字符串存储,该表包含对程序中以编程方式声明或创建的每个唯一文字字符串的单个引用。因此,具有特定值的文字字符串的实例在系统中只存在一次。
例如,如果您将相同的文字字符串分配给多个变量,则运行时会从实习池中检索对文字字符串的相同引用并将其分配给每个变量。
Intern 方法使用实习池来搜索等于 str 值的字符串。如果存在这样的字符串,则返回其在实习池中的引用。如果字符串不存在,则将对 str 的引用添加到实习池,然后返回该引用。.... 如果您试图减少应用程序分配的内存总量,请记住,字符串的实习有两个不需要的副作用。首先,在公共语言运行时 (CLR) 终止之前,分配给 interned String 对象的内存可能不会被释放。
那么,这是否意味着 CLR 为所有正在运行的 .net 应用程序保留一个实习生池?示例:如果程序 A 创建了一个字符串文字“Test”,并且如果另一个程序尝试创建另一个字符串文字“Test”,则使用相同的副本?同样的问题也适用于 JVM。
java - 字符串实习真的有用吗?
前段时间我正在讨论字符串和各种语言,字符串实习的话题出现了。显然,Java 和 .NET 框架会自动对所有字符串以及几种脚本语言执行此操作。从理论上讲,它可以节省内存,因为您最终不会得到同一个字符串的多个副本,并且它可以节省时间,因为字符串相等比较是一个简单的指针比较,而不是 O(N) 遍历字符串的每个字符。
但我想得越多,我就越怀疑这个概念的好处。在我看来,优势主要是理论上的:
- 首先,要使用自动字符串暂留,所有字符串都必须是不可变的,这使得很多字符串处理任务比它们需要的更难。(是的,我听过所有关于不变性的论点。这不是重点。)
- 每次创建新字符串时,都必须根据字符串实习表检查它,这至少是一个 O(N) 操作。(编辑:其中 N 是字符串的大小,而不是表的大小,因为这让人们感到困惑。)因此,除非字符串相等比较与新字符串创建的比率非常高,否则节省的净时间不太可能是一个正值。
- 如果字符串相等表使用强引用,则字符串在不再需要时将永远不会被垃圾回收,从而浪费内存。另一方面,如果表使用弱引用,则字符串类需要某种终结器来从表中删除字符串,从而减慢 GC 过程。(这可能非常重要,具体取决于字符串实习生表的实现方式。在最坏的情况下,从哈希表中删除一个项目可能需要在某些情况下对整个表进行 O(N) 重建。)
这只是我思考实现细节的结果。有什么我错过的吗?在一般情况下,字符串实习是否真的提供了任何显着的好处?
编辑 2:好吧,显然我是在错误的前提下进行操作的。与我交谈的人从未指出弦乐实习对于新创建的弦乐是可选的,实际上给人的强烈印象是相反的情况。感谢 Jon 把事情弄清楚了。另一个接受他的答案。
java - 如何避免 string.intern() 争用并保持低内存占用?
我正在解析一个相当大 (200 MB) 的 XML 文件,该文件会生成一个对象树,每个对象都定义了一堆参数 (key=value)。此数据结构在 Tomcat webapp 中运行并用于查找这些参数。
几个月前,我们在这台服务器上发现了一个堆内存问题。我们可以通过实习参数键和值(其中大多数是非常冗余的)来解决它,这将内存占用从超过 150 MB 减少到低至 20 MB。
今天我正在重新访问服务器,因为人们抱怨启动时间。我正在分析服务器并看到使用 XPP3 解析 XML 需要 40 秒,其中 String.intern() 需要 30 多秒。
我知道这是一个权衡。我知道我可以自己做实习。由于解析 XML 是单线程的,因此简单的 HashMap 也可以完成这项工作。但你知道,这感觉有点奇怪。
是否有人计算过这些数字,看看是否值得放弃 String.intern 以支持不同的解决方案?
那么问题来了?我怎样才能使此类问题的争用尽可能低?
谢谢,斯特凡