http://queue.acm.org/detail.cfm?id=1814327
一个.NET开发人员应该实现B-Heap数据结构,以便在同一虚拟内存页面中维护父子关系吗?在哪里或如何实现?
澄清
换句话说,.NET中是否需要这种类型的数据结构作为原始类型?确实应该在CLR中本地实现或在p/invoke中实现。
当服务器管理员在虚拟机中部署我的.NET应用程序时,这种二叉堆优化有意义吗?如果有,什么时候有意义?(对象数量等)
http://queue.acm.org/detail.cfm?id=1814327
一个.NET开发人员应该实现B-Heap数据结构,以便在同一虚拟内存页面中维护父子关系吗?在哪里或如何实现?
澄清
换句话说,.NET中是否需要这种类型的数据结构作为原始类型?确实应该在CLR中本地实现或在p/invoke中实现。
当服务器管理员在虚拟机中部署我的.NET应用程序时,这种二叉堆优化有意义吗?如果有,什么时候有意义?(对象数量等)
Queue<T>
使用数组进行内部存储。从纯随机访问的角度来看(也就是说,在没有任何分页或CPU缓存刷新成本的情况下),这是一个糟糕的选择;队列几乎总是在一个点添加,然后在另一个点删除,因此,在几乎所有方面,内部实现作为单向链表的效果都要好得多(就遍历队列而言,它也支持 - 在纯随机访问情况下,链表在这方面应该不比数组差)。基于数组的实现比单向链表更好的地方恰恰是在考虑分页和CPU缓存时。微软采用了一种在纯随机访问情况下更差但在实际情况下更好的解决方案,因此他们正在关注分页的影响。这些问题也可以通过其他方式解决。例如,GC的工作方式最小化了所需的分页量,因为它移动对象不仅减少了碎片化,还减少了页面故障。其他集合也采用了使分页不那么频繁的实现方式,而不是最直接的解决方案。
这只是我从我看过的东西中发现的一些问题。我敢打赌,在.NET团队的许多其他地方也考虑到了这些问题。同样适用于其他框架。请考虑,Cliff Click在他的Java无锁哈希表中反复提到的一个大的性能问题(我真的很想完成检查我的C#实现),除了无锁并发性(整个练习的重点)之外,就是缓存行;这也是他没有解决的另一个性能问题!
请注意,大多数集合的大多数用途都将适合于一个页面!
如果您正在实现自己的集合,或者将标准集合放入特别重要的使用中,则需要考虑这些问题(有时“不是问题”足够思考,有时则不然),但这并不意味着我们从BCL中获得的东西没有被考虑过。
Queue <T>
是经典的,因为单链表在纯随机访问上会击败数组,但数组在分页机器上获胜,而数组是他们所选择的。从我查看的内容来看,Mono也注意到了分页和缓存行的重要性(尤其是HashSet <T>
,因为我需要一些东西... - Jon HannaHashSet<T>
但有一些自定义要求(我希望在由于重复而导致 Add()
失败时能够获取现有的引用类型,以实现一种内部池式集合),因此我对它进行了相当多的研究。关于哈希集和字典,它们都使用再探测而不是开放表格,这可能受到这些方法处理分页和 CPU 缓存更好的影响(尽管还有其他因素支持它们)。还有其他我不知道的东西,但很明显,MS 和 Mono 都非常重视这个问题。 - Jon Hanna如果你有一个特别特殊的情况和算法,那么可能从这种优化中受益。
但是一般来说,在重新实现CLR框架的核心部分(在CLR之上,也就是托管代码中)时,你比CLR团队更高效的机会非常渺茫。所以,我不建议这样做,除非你已经对当前实现进行了详尽的性能分析,并明确确定了与内存中数据位置相关的问题。即使如此,通过调整算法以更好地与CLR内存管理方案配合,你将获得更多回报,而不是试图绕过或解决它。