.net 为什么默认情况下只有文本字符串保存在实习池中?

rbpvctlc  于 2022-11-26  发布在  .NET
关注(0)|答案(3)|浏览(124)

为什么默认情况下只有文本字符串保存在实习池中?
MSDN的示例:

String s1 = "MyTest";
String s2 = new StringBuilder().Append("My").Append("Test").ToString(); 
String s3 = String.Intern(s2); 
Console.WriteLine("s1 == '{0}'", s1);
Console.WriteLine("s2 == '{0}'", s2);
Console.WriteLine("s3 == '{0}'", s3);
Console.WriteLine("Is s2 the same reference as s1?: {0}", (Object)s2==(Object)s1); 
Console.WriteLine("Is s3 the same reference as s1?: {0}", (Object)s3==(Object)s1);

/*
This example produces the following results:
s1 == 'MyTest'
s2 == 'MyTest'
s3 == 'MyTest'
Is s2 the same reference as s1?: False
Is s3 the same reference as s1?: True
*/
6bc51xsx

6bc51xsx1#

简短的回答:暂存文字字符串在运行时是 * 便宜的 * 并且 * 节省内存 *。暂存非文字字符串在运行时是 * 昂贵的 * 并且因此 * 节省了少量的内存以换取使普通情况更慢 *。
运行时字符串“优化”的成本并没有为收益买单,因此实际上并不是一种优化。字符串的成本很低,因此确实为收益买单。
我在这里更详细地回答你的问题:
https://ericlippert.com/2009/09/28/string-interning-and-string-empty

jdgnovmf

jdgnovmf2#

语言设计者认为,暂存每个中间字符串值的成本不值得性能成本。暂存可回收垃圾的字符串需要一个全局弱Map,当您有大量线程时,这可能成为一个瓶颈。

wfauudbj

wfauudbj3#

在大多数字符串使用场景中,即使有一个零成本的弱引用实习池(理想的实习实现),实习字符串也几乎不会提供任何好处。为了让字符串实习提供任何好处,有必要在合理的“长”时间内保持对一致的字符串的多个引用。
请考虑以下两个程序:
1.从一个文本文件中输入100,000行,每行包含一些任意的文本,然后输入100,000个五位数字。将读入的每个数字视为读入的100,000行列表中从零开始的索引,并将相应的行输出到输出。
1.从文本文件中输入100,000行,输出包含字符序列“fnord”的每一行。
对于第一个程序,根据文本文件的内容,字符串实习可能会节省大约50,000:1的内存(如果一行包含100,000个相同的长文本行),或者可能代表完全的浪费(如果所有100,000行都不相同)。在没有字符串实习的情况下,一个包含100,000个相同行的输入文件将导致同一字符串的100,000个活示例存在simultaneously。使用字符串实习,活示例的数量可以减少到两个。当然,编译器甚至无法猜测输入文件是否倾向于包含100,000个相同行、100,000个不同行,或者介于两者之间。
对于第二个程序,即使是一个理想的字符串实习实现也不太可能提供太多好处。即使输入文件的所有100,000行碰巧都相同,实习也不能保存太多内存。实习的效果不是防止创建冗余的字符串示例,而是允许冗余串示例被标识和丢弃。由于每一行一旦被检查就可以被丢弃,实习所能买到的唯一东西就是(理论上)能够比其他可能的方式稍微快(非常)一点地丢弃冗余的字符串示例。
在某些情况下,缓存某些“中间”字符串结果可能会有好处,但这是一项真正最好留给程序员的任务。例如,我有一个程序,需要将大量字节转换为两位数的十六进制字符串。为了方便这一点,我有一个255个字符串的数组,其中保存了从00到FF的字符串等效值。我知道,平均来说,数组中的每个字符串至少会被使用成百上千次,所以缓存这些字符串是一个巨大的胜利。另一方面,字符串只能被缓存,因为我知道它们代表什么。我可能知道,对于任何n 0-255,String.Format("{0:X2}",n)总是会产生相同的值,但我不希望编译器知道这些。

相关问题