【发布时间】:2013-08-13 04:06:27
【问题描述】:
我正在尝试在 java 中实现一个面向列的数据存储引擎。我想知道是否有任何其他方法可以为动态增长的数组实现连续内存分配。
HashMaps 无法在扩展/调整大小时分配连续的内存块。
即使通过创建更大大小的新固定数组并将值从旧固定数组复制到这个新数组,看起来也是实现连续性的唯一选择,但与 for ex 相比,这非常慢。假设您在当前大小为 100 万的列(固定数组)中已有 100 万条记录,您需要在 1000001 位置插入新值,然后 jvm 必须创建大小为 1000001 的新数组并将所有值复制到新的更大尺寸的数组(仅插入一个值)并保持连续性。
ArrayList 在内部的工作方式与上述相同(分配新数组 + 复制旧值等)。因此,作为线程安全的具有额外同步开销的向量。
因此,通过在初始化期间创建一个巨大的固定数组来分配大量连续内存的另一种方法会导致大量未使用的内存,这不是一个可行的解决方案。
如果有更好的选择,请提供帮助。例如。类似(如果可以在 Java 中实现)知道当前固定数组中最后一个元素的地址并以某种方式检查下一个连续可用块是否可用?如果是这样,那么使用它来存储新值以及更新数组索引以适应此新更改以维持 O(1) 时间读取访问?
谢谢。
【问题讨论】:
-
嗯,这些基本上是您的选择:分配很多开始并知道您不必复制但同时“浪费”内存,或者分配更小的块并根据需要进行复制。大小合理的块的链表是一个“中间地带”。
-
为什么连续记忆对你很重要?此外,ArrayList 由数组支持,因此是连续的内存。当然,你也可以像
ArrayList那样手工做同样的事情(过程中避免一些拳击),真的没那么难。 -
我刚刚检查了 ArrayList 的 jdk 内部实现,并知道内部它被初始化为默认大小 10,然后执行创建新数组 + 1 大小的相同过程 -> 将旧值复制到这个新的,当它需要扩展 add() 方法时。所以我认为它们分配有连续的内存块(由数组索引支持),但在重新调整巨大数组列表的大小时会影响性能。
-
那么还有其他解决方案吗?例如。知道当前固定数组中最后一个元素的地址,并以某种方式检查下一个连续可用块是否可用?如果是这样,那么使用它来存储新值以及更新数组索引以适应此新更改以维持 O(1) 时间读取访问?
-
你真的做过基准测试吗?我强烈建议您高估了调整大
ArrayLists 的“性能影响”。 (对于初学者来说,add摊销 O(1) 甚至考虑到调整大小。)
标签: java memory-management jvm dynamic-arrays