Ani*_*Ani 11 .net java boxing memory-management value-type
考虑:
int a = 42;
// Reference equality on two boxed ints with the same value
Console.WriteLine( (object)a == (object)a ); // False
// Same thing - listed only for clarity
Console.WriteLine(ReferenceEquals(a, a)); // False
Run Code Online (Sandbox Code Playgroud)
显然,每个装箱指令分配一个单独的盒装实例Int32,这就是为什么它们之间的引用相等失败的原因.此页面似乎表明这是指定的行为:
box指令将'raw'(未装箱)值类型转换为对象引用(类型O).这是通过创建新对象 并将值类型中的数据复制到新分配的对象中来实现的.
但为什么会出现这种情况呢?有没有令人信服的理由为什么CLR不选择Int32为所有原始值类型(都是不可变的)保持盒装s 的"缓存" ,甚至更强的共同值?我知道Java有这样的东西.
在没有泛型的时代,对于ArrayList主要由小整数组成的大型内存需求以及GC工作负载,它是否会帮助很多?我也肯定存在一些现代的是.NET应用程序做使用泛型,但是由于各种原因(反射,接口分配等),跑起来大拳分配可与可大量减少(什么似乎是)一个简单的优化.
那是什么原因?我没有考虑过一些性能影响(我怀疑是否测试该项目是否在缓存中等将导致净性能损失,但我知道什么)?实施困难?不安全代码的问题?打破向后兼容性(我想不出任何好的理由,为什么一个精心编写的程序应该依靠现有的行为)?或者是其他东西?
编辑:我真正建议的是"常见" 原语的静态缓存,就像Java所做的那样.有关示例实现,请参阅Jon Skeet的回答.我知道在运行时为任意,可能是可变的值类型或动态 "memoizing"实例执行此操作是完全不同的事情.
编辑:为清晰起见改变了标题.
Jon*_*eet 11
我发现引人注目的一个原因是一致性.正如你所说,Java 确实将盒装值缓存在一定范围内......这意味着编写一段有效的代码非常容易:
// Passes in all my tests. Shame it fails if they're > 127...
if (value1 == value2) {
// Do something
}
Run Code Online (Sandbox Code Playgroud)
我一直被这种方式所困扰 - 幸运的是,在测试中而不是生产代码,但是在某个给定范围之外有一些显着改变行为的东西仍然是令人讨厌的.
不要忘记任何条件行为也会导致所有装箱操作的成本- 所以在不使用缓存的情况下,你实际上发现它更慢(因为它首先必须检查是否使用缓存).
如果你真的想编写自己的缓存盒操作,当然,你可以这样做:
public static class Int32Extensions
{
private static readonly object[] BoxedIntegers = CreateCache();
private static object[] CreateCache()
{
object[] ret = new object[256];
for (int i = -128; i < 128; i++)
{
ret[i + 128] = i;
}
}
public object Box(this int i)
{
return (i >= -128 && i < 128) ? BoxedIntegers[i + 128] : (object) i;
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
object y = 100.Box();
object z = 100.Box();
if (y == z)
{
// Cache is working
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
777 次 |
| 最近记录: |