二叉堆 vs (新)B-堆:它应该在CLR/.NET中实现吗?在哪里实现?

3
以下文章讨论了一种替代堆结构,考虑到大多数服务器是虚拟化的,因此大多数内存被分页到磁盘上。

http://queue.acm.org/detail.cfm?id=1814327

一个.NET开发人员应该实现B-Heap数据结构,以便在同一虚拟内存页面中维护父子关系吗?在哪里或如何实现?

澄清
换句话说,.NET中是否需要这种类型的数据结构作为原始类型?确实应该在CLR中本地实现或在p/invoke中实现。

当服务器管理员在虚拟机中部署我的.NET应用程序时,这种二叉堆优化有意义吗?如果有,什么时候有意义?(对象数量等)


如果你正在处理需要优先队列的几千万条目的项目,那么调查一下是值得的。请注意,这篇文章是关于服务器农场的。 - H H
2个回答

1
在某种程度上,BCL集合似乎确实考虑了分页问题。它们还考虑了CPU缓存问题(在某些方面重叠,因为内存的局部性可能会影响两者,尽管方式不同)。
考虑到Queue<T>使用数组进行内部存储。从纯随机访问的角度来看(也就是说,在没有任何分页或CPU缓存刷新成本的情况下),这是一个糟糕的选择;队列几乎总是在一个点添加,然后在另一个点删除,因此,在几乎所有方面,内部实现作为单向链表的效果都要好得多(就遍历队列而言,它也支持 - 在纯随机访问情况下,链表在这方面应该不比数组差)。基于数组的实现比单向链表更好的地方恰恰是在考虑分页和CPU缓存时。微软采用了一种在纯随机访问情况下更差但在实际情况下更好的解决方案,因此他们正在关注分页的影响。
当然,从外部来看,这并不明显 - 也不应该如此。从外部我们想要像队列一样工作的东西;使内部高效是另一个问题。

这些问题也可以通过其他方式解决。例如,GC的工作方式最小化了所需的分页量,因为它移动对象不仅减少了碎片化,还减少了页面故障。其他集合也采用了使分页不那么频繁的实现方式,而不是最直接的解决方案。

这只是我从我看过的东西中发现的一些问题。我敢打赌,在.NET团队的许多其他地方也考虑到了这些问题。同样适用于其他框架。请考虑,Cliff Click在他的Java无锁哈希表中反复提到的一个大的性能问题(我真的很想完成检查我的C#实现),除了无锁并发性(整个练习的重点)之外,就是缓存行;这也是他没有解决的另一个性能问题!

请注意,大多数集合的大多数用途都将适合于一个页面!

如果您正在实现自己的集合,或者将标准集合放入特别重要的使用中,则需要考虑这些问题(有时“不是问题”足够思考,有时则不然),但这并不意味着我们从BCL中获得的东西没有被考虑过。


谢谢,+1;内存布局是否与最终可能分页到磁盘的内容对齐?如果微软已经实现了这一点并且没有告诉我们,那么为微软加1。我想知道Mono的实现是什么样子的。 - makerofthings7
关于对齐,我不太清楚,但在我查看的案例中,细节正在以适合该抽象级别的方式利用分页和缓存行,就像链接到文章中的B * -tree堆与B-heap相比。 Queue <T>是经典的,因为单链表在纯随机访问上会击败数组,但数组在分页机器上获胜,而数组是他们所选择的。从我查看的内容来看,Mono也注意到了分页和缓存行的重要性(尤其是HashSet <T>,因为我需要一些东西... - Jon Hanna
基于 HashSet<T> 但有一些自定义要求(我希望在由于重复而导致 Add() 失败时能够获取现有的引用类型,以实现一种内部池式集合),因此我对它进行了相当多的研究。关于哈希集和字典,它们都使用再探测而不是开放表格,这可能受到这些方法处理分页和 CPU 缓存更好的影响(尽管还有其他因素支持它们)。还有其他我不知道的东西,但很明显,MS 和 Mono 都非常重视这个问题。 - Jon Hanna
现在我想起来了,如果对象小于页面大小,则允许跨越页面边界,我会感到惊讶(虽然我不确定)。一旦你的大小超过页面大小,你无论如何都会跨越它(事实上,B+树设计的一个特点是,尽管大块可以提供更好的局部性,但你不希望它们跨越页面)。由于保持I/O缓冲区<页面大小是初学者学习的内容,所以如果这已经被考虑过了,或者那些在这个层面工作的人认为这不重要,因为他们在这方面比我知道得更多而做出了明智的决定,我会感到惊讶。 - Jon Hanna

0

如果你有一个特别特殊的情况和算法,那么可能从这种优化中受益。

但是一般来说,在重新实现CLR框架的核心部分(在CLR之上,也就是托管代码中)时,你比CLR团队更高效的机会非常渺茫。所以,我不建议这样做,除非你已经对当前实现进行了详尽的性能分析,并明确确定了与内存中数据位置相关的问题。即使如此,通过调整算法以更好地与CLR内存管理方案配合,你将获得更多回报,而不是试图绕过或解决它。


问题是关于二叉堆数据结构,而不是关于(替换)托管堆的。 - H H
我认为为这种情况提供CLR支持会很好,这样可以将实现细节从.NET开发人员中抽象出来。也许它可以在CLR中实现,也许可以在库中实现。无论哪种方式,这都是一个有趣的优化。 - makerofthings7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接