我需要在我的对象中存储哪些值已经被处理过,我怀疑什么会花费更多的性能,我应该创建一个存储的数组:
更新
我的目标是,处理引用上的数据集合应该花费更少的内存,因为我将获得父实例类型的音调。
我不太关心检索时间(即collection.Contains(reference))。
所以我的问题是以上数组中的内存会花费多少内存。
答案 0 :(得分:3)
存储对象的引用似乎是最简单和最低内存成本选项。
如果你正在使用这个“已经处理过”检查,最好的选择(最快的检查)可能是在你的班级上实施Object.Equals和Object.GetHashCode,然后使用HashSet<T>
。 HashSet<T>
对此很好,因为它提供了O(1)Contains() method。
如果您无法更改类以允许散列,则可以为对象实现IEqualityComparer。
答案 1 :(得分:0)
除非对象的不同值的可能范围小于2 ^ 32,否则.NET样式哈希码不是一个选项,否则您将得到误报(并且考虑到生日悖论,这可能比你可能会想到即使有很好的哈希函数)。 Hashcodes提供了一个零或多个项目的快速链接,然后检查它们是否相等。因此,基于哈希码的解决方案还需要您存储对每个对象的引用,因此在内存中只能存储小于引用的内容。
如果对象不能被垃圾收集(即它们仍然“活着”到应用程序的另一部分),则存储引用的成本将取决于体系结构为4或8个字节。如果它们可能是GC'd,则成本取决于该对象的图形大小。
现在,如果您可以创建自己的小于该对象的无损哈希对象,则可以节省内存。 E.g:
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,则更小,如果它们仍然在内存中则毫无意义。
如果您决定将这些存储在HashSet中,那么有一种哈希和相等的方法(可能的值的知识可以改善哈希的好处)。 HashSet不会是最节省内存的集合,尽管可能是因为在所有这些比较中你都会对此产生额外的压力,你需要更快的查找。这是理论上的实验领域(特别是因为细节根据你的对象而变化)。如果您可以查看不断扫描阵列的查找时间复杂度,那么这是您最好的选择。
如果没有可能比原始类型更小的对象允许完全相关的相等比较,那么这种方法不起作用。