C# 二进制堆与(新)B堆:它应该在CLR/.NET中实现吗?在哪里?

C# 二进制堆与(新)B堆:它应该在CLR/.NET中实现吗?在哪里?,c#,optimization,clr,heap,binary-tree,C#,Optimization,Clr,Heap,Binary Tree,下面的文章讨论另一种堆结构,它考虑到大多数服务器都是虚拟化的,因此大多数内存都被分页到磁盘 NET开发人员是否可以(或应该)实现B堆数据结构,以便在同一虚拟内存页中维护父子关系?如何或在何处实施 澄清 换句话说,在.NET中是否需要这种类型的数据结构作为初始类型?如果为True,则应在CLR或p/invoke中以本机方式实现它 当服务器管理员在虚拟机中部署my.NET应用程序时,这种二进制堆优化有意义吗?如果是,什么时候才有意义?(对象数量等)如果您有一个特别特殊的场景和算法,那么您可能会从

下面的文章讨论另一种堆结构,它考虑到大多数服务器都是虚拟化的,因此大多数内存都被分页到磁盘

NET开发人员是否可以(或应该)实现B堆数据结构,以便在同一虚拟内存页中维护父子关系?如何或在何处实施

澄清
换句话说,在.NET中是否需要这种类型的数据结构作为初始类型?如果为True,则应在CLR或p/invoke中以本机方式实现它


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

如果您有一个特别特殊的场景和算法,那么您可能会从这种优化中受益


但一般来说,当重新实现CLR框架的核心部分时(在我可能添加的CLR之上,即托管代码中),您比CLR团队更高效地完成这项工作的机会非常渺茫。所以我不会推荐它,除非您已经分析了当前实现的最新情况,并且积极地发现了与内存中数据的局部性相关的问题。即使如此,通过调整算法,使其更好地与CLR内存管理方案配合使用,然后尝试绕过或绕过它,您也会获得更大的回报。

至少在一定程度上,BCL集合似乎考虑了分页问题。它们还考虑了CPU缓存问题(这在某些方面是重叠的,因为内存的局部性可能会以不同的方式影响两者)

假设
队列
使用数组作为内部存储。在纯粹的随机访问条件下(也就是说,分页或CPU缓存刷新从来没有任何成本),这是一个糟糕的选择;队列几乎总是在一个点上单独添加到,在另一个点上从中删除,因此作为单链接列表的内部实现几乎在所有方面都会获胜(就此而言,在遍历队列(它也支持队列)方面,在纯随机访问情况下,链表在这方面不应该比数组差太多)。基于阵列的实现优于单链表的地方恰恰是在考虑分页和CPU缓存时。MS选择了一种解决方案,这种解决方案在纯随机访问情况下更差,但在分页重要的实际情况下更好,因此他们关注分页的效果

当然,从外部看,这并不明显——也不应该如此。从外部看,我们想要的是像队列一样工作的东西;让内部高效是另一个问题

这些问题也可以通过其他方式得到解决。例如,GC的工作方式可以最大限度地减少必要的分页量,因为它的移动对象不仅可以减少碎片,还可以减少页面错误。其他集合的实现方式也可以使分页频率低于最直接的解决方案所建议的频率

这只是我从我所看到的东西中发现的一些东西。我打赌好的钱也会在.NET团队工作的许多地方被考虑到。同样的,其他java框架也可以考虑。(我已经检查完我的C#实现)除了无锁并发(练习的重点)之外,还有缓存线;这也是他没有忽略的另一个性能问题

还要考虑的是,大多数集合的大多数用途无论如何都要放在一个页面中


如果您正在实现自己的集合,或者正在大量使用标准集合,那么这些都是您需要考虑的事情(有时“不,不是问题”就足够了,有时不是)但这并不意味着我们还没有考虑从BCL中获得的信息。

如果您正在研究的内容需要一个包含1亿个条目的优先级队列,则需要进行调查。请注意,这篇文章是关于服务器场的。问题是关于仓位堆数据结构,而不是(替换)托管堆。我认为在这种情况下拥有CLR支持会很好…其中实现细节是从.NET开发人员那里抽象出来的。也许它可以在CLR中实现。也许它可以在库中实现。无论哪种方式,这都是一个有趣的优化。谢谢,+1;内存布局是否与ul一致如果他们已经实现了这一点,并且从未告诉过我们,我会立即将其分页到磁盘?+1。我想知道Mono的实现是什么样的。关于对齐,我不知道,但在我看过详细信息的情况下,详细信息正在以适合于该抽象级别的方式利用分页和缓存线,就像B*树一样ke heap在链接到的文章中超越了B堆。
Queue
是一个经典,因为单链表在纯随机访问上会击败array,但array在分页机器上胜出,array就是他们追求的目标。Mono也注意到了一个事实,即分页和缓存线很重要,从我对它们的观察来看(
HashSet
尤其是因为我需要一些基于
HashSet
但有一些自定义要求的东西(对于某种内部池样式的集合,
Add()
由于重复而失败时,我希望能够获取现有的引用类型)因此,我仔细研究了它。对于散列集和字典,它们都使用重新编译而不是打开表,这一事实可能会受到那些更好地处理分页和CPU缓存的方法的影响(尽管还有其他fa)