在使用CLR Profiler进行一些实验后,我发现:
Node[,] n = new Node[100,23]; //'84,028 bytes, is not placed in LOH
Node[,] n = new Node[100,24]; //'86,428 bytes, is
public struct Node {
public int Value;
public Point Point;
public Color Color;
public bool Handled;
public Object Tag;
}
在运行期间,我如何知道在大对象堆(LOH)中分配了一组结构(或任何数组)?
答案 0 :(得分:2)
任何大于85,000字节的对象都将存储在LOH上。这是一篇关于.Net Memory Management的精彩博文。
答案 1 :(得分:1)
从您的评论中,我认为您实际上并不需要知道该对象是否会继续使用LOH。当你输入一个“太大”的值时,当你真正想做的就是向用户显示警告时,这是否是你应用程序减速的实际原因是无关紧要的。
所以我建议稍微简单一些:只需使用一些试错法来确定截止值。如果他们输入的尺寸超过了试错值,则显示警告。
至于你的实际性能问题,你可以简单地分配一堆“较小的”一维数组,而不是分配一个大的二维数组。而不是:
Node[,] n = new Node[100,100]; // this will go the LOH
你这样做:
Node[][] n = new Node[100][];
for(int i = 0; i < n.Length; i++) {
n[i] = new Node[100]; // none of these will be on the LOH
}
你总共拥有相同数量的节点,但LOH上什么都没有。就个人而言,我认为你可能会发现性能实际上并没有那么大的不同,但是尝试一下也许是值得的。
答案 2 :(得分:1)
您可以在分配后立即找到。使用GC.GetGeneration(object)重载来获取对象所在的世代号。对于LOH,这将是2.
Node[,] n = new Node[100,23];
// GC.GetGeneration(n) should give 0
Node[,] n = new Node[100,24];
// GC.GetGeneration(n) should give 2
注意,这有一些限制,对于生产代码来说绝不是一种正确的方法,我假设:如果您稍后查询该数字,该对象可能已经从Gen 0移动到Gen 2。我不知道要区分Gen2(小对象)堆和LOH。此外,对于我测试的所有.NET版本,LOH上的对象返回的数字是2。但我在实际规范中找不到这个,所以它也可能是一个变化的问题。