我试图在C#中使用ObjectIDGenerator在序列化期间生成一个唯一的ID,但是,这个类在XBox360或Windows Phone 7 .NET框架中不可用(它们使用的是.NET的紧凑版本)。我使用Object到Int64的字典实现了一个版本,并且能够获得完全正常工作的版本,但是,性能并不令人满意。我正在按照成千上万个对象的顺序进行序列化,目前这是保存/加载性能的最大瓶颈。使用PC上的实际.NET实现,大约需要0.3秒来序列化大约20,000个对象。使用我的实现,大约需要6秒钟。
在分析中,我发现重度击球手是.TryGetValue和.Add在字典上(这是有意义的,因为它既是索引并且添加到哈希映射)。更重要的是,正在调用虚拟相等运算符而不是简单地比较引用,因此我实现了仅使用ReferenceEquals的IEqualityComparer(这导致了速度增加)。
有没有人能够更好地了解ObjectIDGenerator的更好实现?谢谢你的帮助!
我的实施:http://pastebin.com/H1skZwNK
[编辑] 另一个注意事项,分析结果表明,对象比较/ ReferenceEquals仍然是瓶颈,命中数为43,000,000。我想知道是否有办法将数据存储在这个对象旁边而不必在哈希映射中查找...
答案 0 :(得分:4)
是否可以为每个对象而不是Int32
使用Object
Id属性/句柄?这可能有所帮助。看起来您无论如何都要为每个对象分配一个Id类型编号,然后只有您根据Object引用而不是Id查找。您可以在每个对象中保留对象ID(您的Int64
)并将字典改为Dictionary<Int64, Object>
吗?
您可能还想查看SortedDictionary<TKey, TValue>
或SortedList<TKey, TValue>
的表现是好还是坏。但如果您的主要瓶颈在IEqualityComparer
,那么这些可能无济于事。
<强>更新强>
在查看ObjectIDGenerator
类API之后,我可以看到为什么你不能做我最初建议的那样;你在创造ids!
ObjectIDGenerator
似乎是手动实现自己的哈希表(它分配object[]
和并行long[]
并在添加对象时调整它们的大小。它还使用RuntimeHelpers.GetHashCode(Object)
来计算其哈希值,而不是IEqualityComparer
,这可能是你的perf的一大推动,因为它总是调用Object.GetHashCode()
并且不对派生类型进行虚拟调用(或您的案例中的接口调用IEqualityComparer
)。