【发布时间】:2016-09-23 09:26:10
【问题描述】:
HashMap 中有大约 5-10M 条目,我无法更改代码结构。我正在运行java 和-Xms=512m -Xmx=1024m。 HashMap 构造函数中避免java.lang.OutOfMemoryError: GC overhead limit exceeded 的最佳容量/负载因子值是多少?
private final Map<String, ReportResultView> aggregatedMap = new HashMap<>(????, ????);
【问题讨论】:
-
通过调整这些参数,您无能为力。您可以尝试避免调整地图大小,但这意味着您必须为最坏的情况(您可能需要的最大条目数)预先调整大小。改变负载系数是不值得的。
-
如果你有10M的条目,最好的容量是10M,不过不用担心。一旦你添加了所有 10M 条目,它将具有(至少)该容量,这是不可避免的。您传递给构造函数的值是初始容量,它主要影响初始插入性能,当太低时,仅此而已。一旦添加了这些值,它就不再有任何影响了。
-
@holger 它会影响调整大小期间发生的内存使用峰值。还要注意糟糕的 API,其中“容量”不是在调整大小之前可以插入的条目数,而是存储桶数组的原始大小。您必须除以负载因子才能获得对用户有意义的大小。
-
@Marko Topolnik:比这更复杂。如果您指定 10M,由于四舍五入到 2 的下一个幂,您实际上将获得 >16M 的容量,因此在任何负载因子 >0.6(默认值为 0.75)的情况下,您可以放置 10M 条目而无需调整大小。请注意,这不是我们所说的“糟糕的 API”,而是“糟糕的实现”。
-
这取决于你的目标。如果您指定 10M 作为初始容量,但只放置 5M 条目,那么您显然是在浪费空间。如果您指定 5M 作为初始容量,但放入 10M 条目,那么您将在中间进行一次重新哈希操作。因此,最大性能是您的目标,您可能希望避免重新哈希操作,但如果更有可能拥有 5M-6M 条目并且您希望减少平均内存占用,您可能会接受在某些情况下可能发生的一次重新哈希操作。
标签: java dictionary optimization hashmap java-8