代码之家  ›  专栏  ›  技术社区  ›  Shimmy Weitzhandler 500 - Internal Server Error

.NET是否应存储引用或值?

  •  0
  • Shimmy Weitzhandler 500 - Internal Server Error  · 技术社区  · 14 年前

    我需要在我的对象中存储那些已经处理过的值,我怀疑什么会花费更多的性能,我是否应该创建一个数组来存储:

    • 实例引用(它们不是结构,只是引用类)

    更新
    我的目标是在处理的引用上收集数据应该花费尽可能少的内存,因为我将拥有父实例类型的音调。

    所以我的问题是 上面的数组是什么?内存成本更低。

    2 回复  |  直到 14 年前
        1
  •  3
  •   Shimmy Weitzhandler 500 - Internal Server Error    14 年前

    存储对对象的引用似乎是最简单、内存成本最低的选择 .

    如果您将此用于“是否已处理”检查,那么最好的选择(对于最快的检查)可能是实现 Object.Equals Object.GetHashCode 在你的课上,然后用 HashSet<T> . 哈希集<T> 这很好,因为它提供了一个O(1) Contains() method .

    如果不能更改类以允许散列,也可以实现 IEqualityComparer 对于对象。

        2
  •  0
  •   BenMorel Pankaj Kumar    11 年前

    .NET样式的哈希码不是一个选项,除非对象的不同值的可能范围小于2^32,否则会出现误报(考虑到生日悖论,即使使用很好的哈希函数,这种情况也可能比您想象的更频繁)。哈希代码提供了一个到包含零个或多个项的bucket的快速链接,然后检查这些项是否相等。因此,hashcode基本解决方案将要求您存储对每个对象的引用,因此在内存中不能比仅存储引用小。

    如果对象不能被垃圾收集(即它们对于应用程序的另一部分仍然是“活动的”),那么存储引用的成本将是4或8字节,具体取决于体系结构。如果它们可以被GC'd,那么成本取决于该对象的图形的大小。

    public class ObjectOfInterest
    {// all fields public for sake of simplicity in example
        public int ID; // this is important diff id - diff object.
        public int ParID; // this is unimportant, as same for all objects processed here.
        public ParentType Parent; // this is just memoised based on _parID;
        public decimal Val; // this is important.
        public string Name; // unimportant for our purposes.
        public RelatedType Stuff; // memoised based on _id
    }
    

    然后我们可以产生一个相关的:

    public struct HashObject
    {
        private readonly int _id;
        private readonly decimal _val;
        public HashObject(ObjectOfInterest ooi)
        {
            _id = ooi.ID;
            _val = ooi.Val;
        }
        public bool Matches(ObjectOfInterest ooi)
        {
            return _id == ooi.ID && _val == ooi.Val;
        }
        // because one of the options as to how to store *this* is hashing
        public bool Equals(HashObject ho)
        {
            return _id == ho._id && _val == ooi._val;
        }
        public override bool Equals(object obj)
        {
            return Equals(obj as HashObject);
        }
        public int GetHashCode()
        {
            unchecked
            {
                return _val.GetHashCode() ^ (_id << 16) ^ (_id >> 16);
            }
        }
    }
    

    现在,我们存储HashObjects并使用它们来记录我们所做的工作。在这种情况下,我们将占用至少20个字节来存储这个结构,再加上我们必须存储它的任何方法的开销。如果感兴趣的ObjectOfInterest现在可以被GC'd,则更小;如果它们仍然在内存中,则没有意义。

    如果您决定将它们存储在HashSet中,那么有一种hash和equality方法(了解可能的值可以提高hash的质量)。HashSet不会是内存效率最高的集合,尽管可能是因为在所有这些比较中您对它施加了额外的压力,所以确实需要更快的查找。这是实验而不是理论的领域(特别是因为细节会随着你的物体而改变)。如果您可以考虑不断扫描阵列的查找时间复杂性,那么这是您的最佳选择。

    如果没有一个比原始类型更小的对象允许进行完全相关的相等比较,那么这种方法就行不通了。