C# 在托管代码中,如何实现良好的引用局部性?

C# 在托管代码中,如何实现良好的引用局部性?,c#,java,python,optimization,memory-management,C#,Java,Python,Optimization,Memory Management,由于RAM看起来很慢,而且这句话也意味着对内存的访问现在被认为与磁盘访问的速度一样慢,所以我确实希望最大限度地提高高性能应用程序内存中引用的局部性。例如,在排序索引中,我希望相邻值接近(与哈希表不同),并且我希望索引指向的数据也接近 在C语言中,我可以使用专门的内存管理器快速创建数据结构,就像(非常复杂)的开发人员所做的那样。通过对指针的直接控制,它们甚至可以在指针值本身中编码额外的信息。当我在Python、Java或C#中工作时,我故意远离这种类型的解决方案一个(或多个)级别的抽象,我委托JI

由于RAM看起来很慢,而且这句话也意味着对内存的访问现在被认为与磁盘访问的速度一样慢,所以我确实希望最大限度地提高高性能应用程序内存中引用的局部性。例如,在排序索引中,我希望相邻值接近(与哈希表不同),并且我希望索引指向的数据也接近

在C语言中,我可以使用专门的内存管理器快速创建数据结构,就像(非常复杂)的开发人员所做的那样。通过对指针的直接控制,它们甚至可以在指针值本身中编码额外的信息。当我在Python、Java或C#中工作时,我故意远离这种类型的解决方案一个(或多个)级别的抽象,我委托JIT编译器和优化运行时,为我在低级别上做一些巧妙的技巧

尽管如此,我想,即使在这种高度抽象的情况下,也有一些东西在语义上可以被视为“更接近”,因此在较低的层次上可能实际上更接近。例如,我想知道以下几点(我的猜测在括号中):

  • 我是否可以期望阵列是相邻的内存块(是)
  • 同一实例中的两个整数是否比同一类的不同实例中的两个更接近(可能)
  • 对象是否在内存中占据连续区域(否)
  • 只有两个
    int
    字段的对象数组和有两个
    int[]
    字段的单个对象之间有什么区别?(此示例可能是特定于Java的)
我开始在Java环境中思考这些问题,但我的思考变得更加普遍,因此我建议不要将其视为Java问题。

  • 在.NET中,数组的元素肯定是连续的。在Java中,我希望它们在大多数实现中都会出现,但似乎不能保证
  • 我认为有理由假设字段实例使用的内存位于单个块中。。。但不要忘记,其中一些字段可能是对其他对象的引用
对于Java数组部分,包括以下注释,隐藏在关于字符串的讨论中:

例如,Java虚拟机可能不会连续存储阵列

对于最后一个问题,如果您有两个
int[]
,那么这些数组中的每一个都将是一个连续的内存块,但它们在内存中可能“相距很远”。如果有一个包含两个整型字段的对象数组,那么每个对象之间的距离可能很长,但每个对象中的两个整数将非常接近。可能更重要的是,由于每个对象的开销,使用“大量对象”解决方案将占用更多内存。在.NET中,您可以使用一个带有两个整数的自定义结构,并拥有一个由这些整数组成的数组,这样可以将所有数据保存在一个大块中

我相信,在Java和.NET中,如果在一个线程中快速连续地分配大量小型对象,那么这些对象可能具有良好的引用位置。当GC压缩堆时,这可能会有所改善,或者如果堆具有

A B C D E
压实至

A D E B
(收集C的地方)-突然之间,A和B之间的距离很远,这两个位置以前可能是“接近”的。我不知道这是否真的发生在任何垃圾收集器中(周围有负载!),但这是可能的


基本上,在托管环境中,您对引用位置的控制通常不如在非托管环境中那么多-您必须相信托管环境在管理它方面有足够的能力,通过编码到更高级别的平台,您将节省足够的时间,让您花时间在其他地方进行优化。

首先,您的标题暗示了C。如果我没弄错的话,“托管代码”是微软创造的一个术语

Java原语数组保证是一个连续的内存块。如果你有

int[] array = new int[4];
您可以从JNI(原生C)获取一个
int*p
来指向实际数组。我认为这也适用于Array*类容器(ArrayList、ArrayBlockingQueue等)

我认为,JVM的早期实现将对象作为连续结构,但在较新的JVM中不能假设这一点。(JNI抽象了这一点)

同一对象中的两个整数可能会像您所说的那样“更接近”,但它们可能不是。即使使用相同的JVM,这也可能有所不同


一个有两个int字段的对象就是一个对象,我认为任何JVM都不能保证成员“接近”。带有两个元素的int数组很可能由8字节长的数组支持。

关于数组,这里是CLI(公共语言基础设施)规范的摘录:

应布置阵列元件 在主行中的数组对象中 顺序(即关联的元素 具有最右边的数组维度 应从最低索引到最高索引连续布置。这个 为每个存储分配的实际存储空间 数组元素可以包括 平台特定的填充。(尺寸 以字节为单位返回此存储的 当sizeof指令 应用于该数组的 元素


好的问题!我想我会求助于C++中的扩展,它可以更仔细地管理内存,并且只需要暴露足够的接口,让其他应用程序能够操纵对象。如果我关心性能,我可能会求助于C++扩展。到了这个程度,我怀疑基于虚拟机的语言不适合你;)

我想没有人谈论过Python,所以我会试试

我是否可以期望阵列是相邻的内存块(是)

在python中,数组更像是C中的指针数组