一个Java问题: 怎么支持很大的HashMap?

n
nowwhat2012
楼主 (未名空间)

在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后多次查询这个HashMap。

现在发现这个HashMap很大, 初算了一下估计有70G.

在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space

在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00007febd1000000, 7818182656, 0) failed; error='Not enough space' (errno=12)

机器的OS是Linux Mint 19.2 Tina;memory size 是32G

大伙碰到过这个情形吗?这个怎么解决?

谢谢!
t
trilogy

Is the key or value primitive type? How many entries in the map ?

【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后
: 多次查询这个HashMap。
: 现在发现这个HashMap很大, 初算了一下估计有70G.
: 在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space: 在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO:
os:
: :commit_memory(0x00007febd1000000, 7818182656, 0) failed; error='Not
enough
: space' (errno=12)
: 机器的OS是Linux Mint 19.2 Tina;memory size 是32G
: 大伙碰到过这个情形吗?这个怎么解决?
: 谢谢!

F
Foxman

Use a persistence-enabled data store such as elasticsearch.
【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后
: 多次查询这个HashMap。
: 现在发现这个HashMap很大, 初算了一下估计有70G.
: 在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space: 在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO:
os:
: :commit_memory(0x00007febd1000000, 7818182656, 0) failed; error='Not
enough
: space' (errno=12)
: 机器的OS是Linux Mint 19.2 Tina;memory size 是32G
: 大伙碰到过这个情形吗?这个怎么解决?
: 谢谢!

n
nowwhat2012

谢谢回复。

> Is the key or value primitive type?

No.

> How many entries in the map ?

About 70*10^9 (70 billions).

原以为JVM会自动把这个swap到硬盘上虚拟内存里面的。 但是感觉不是。

【 在 trilogy (Jedi) 的大作中提到: 】
: Is the key or value primitive type? How many entries in the map ?
: os:
: enough

t
trilogy

This need way more than 70G memory, this is 70 billion entries. You have a problem in “big data” domain.

Guess it’s one time job since you were building in memory map without
persistence. Recommend Apache Spark job to join the two data set by key. One dataset would be the map, the other one would be the keys to lookup. Launch the spark job in local mode with 32G memory, it should push pretty hard on the resource usage.

【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 谢谢回复。
: > Is the key or value primitive type?
: No.
: > How many entries in the map ?
: About 70*10^9 (70 billions).
: 原以为JVM会自动把这个swap到硬盘上虚拟内存里面的。 但是感觉不是。

s
sanwadie


Java heap momery 常驻内存,不会被swap。elasticsearch 的性能对内存依赖也很大
。70B
的数据,放在哪儿都不好处理。RDBMS单表70B,性能肯定不行;Elasticsearch,一个
70B的索引,本身用的内存就很吓人 ;搞Hadoop,搭个集群都需要很多机器。还是要看具体应用,数据来源,格式和应用如何使用和处理,当然还有硬件资源情况。

【 在 trilogy (Jedi) 的大作中提到: 】
: This need way more than 70G memory, this is 70 billion entries. You have a
: problem in “big data” domain.
: Guess it’s one time job since you were building in memory map without
: persistence. Recommend Apache Spark job to join the two data set by key.
One
: dataset would be the map, the other one would be the keys to lookup.
Launch
: the spark job in local mode with 32G memory, it should push pretty hard
on
: the resource usage.

s
sanwadie

谢谢分享。level db 看起来不错。不过这个Java port 像个半成品。出于性能和稳定
性,应该考虑 java binding/JNI 方式。放狗搜了一下,看看这个:
https://github.com/fusesource/leveldbjni

【 在 glowinglake (湖清霞远) 的大作中提到: 】
: https://github.com/dain/leveldb

n
netghost

内存 32G,你需要70G,然后觉得出了问题很奇怪?
【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后
: 多次查询这个HashMap。
: 现在发现这个HashMap很大, 初算了一下估计有70G.
: 在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space: 在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO:
os:
: space' (errno=12)
: 机器的OS是Linux Mint 19.2 Tina;memory size 是32G
: 大伙碰到过这个情形吗?这个怎么解决?
: 谢谢!

a
anesthetic


【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后
: 多次查询这个HashMap。
: 现在发现这个HashMap很大, 初算了一下估计有70G.
: 在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space: 在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO:
os:
: :commit_memory(0x00007febd1000000, 7818182656, 0) failed; error='Not
enough
: space' (errno=12)
: 机器的OS是Linux Mint 19.2 Tina;memory size 是32G
: 大伙碰到过这个情形吗?这个怎么解决?
: 谢谢!

直接写成hdf,ssd查起来并不慢。我这很多上T的,都这样搞。
g
glowinglake

Jni看起来更靠谱

【 在 sanwadie (三娃爹) 的大作中提到: 】
: 谢谢分享。level db 看起来不错。不过这个Java port 像个半成品。出于性能和稳定
: 性,应该考虑 java binding/JNI 方式。放狗搜了一下,看看这个:
: https://github.com/fusesource/leveldbjni

a
aaaiii

用redis,配置内存大小

【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后
: 多次查询这个HashMap。
: 现在发现这个HashMap很大, 初算了一下估计有70G.
: 在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space: 在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO:
os:
: :commit_memory(0x00007febd1000000, 7818182656, 0) failed; error='Not
enough
: space' (errno=12)
: 机器的OS是Linux Mint 19.2 Tina;memory size 是32G
: 大伙碰到过这个情形吗?这个怎么解决?
: 谢谢!

L
LeftShark

提供两个思路自己去研究吧

ehcache offload到native memory或者ssd?

或者通过apache ignite搞distributed in-memory grid

【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后
: 多次查询这个HashMap。
: 现在发现这个HashMap很大, 初算了一下估计有70G.
: 在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space: 在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO:
os:
: :commit_memory(0x00007febd1000000, 7818182656, 0) failed; error='Not
enough
: space' (errno=12)
: 机器的OS是Linux Mint 19.2 Tina;memory size 是32G
: 大伙碰到过这个情形吗?这个怎么解决?
: 谢谢!

s
sanwadie

我来帮忙总结一下,各位看看。

1)如果是一次性任务或者硬件资源有限:
1.1)leveldb 或 rocksdb 是个可行的方案
1.2) 考虑上云执行代码
2)如果以后要经常用到,且有预算,就需要多考虑一下,实现从简单到复杂:
2.1)如果就是这一种情况,最简单的就是搞个带256G内存的机器(当然如果数据内存
占用超过200G,就不行了)
2.2)使用高性能SSD,对内存就没有太多要求(本人没有尝试过)- 需要修改代码
2.3)使用leveldb 和 rocksdb + 可选的 SSD,这个是一种很通用,也非常简便的方法 - 需要修改点代码
2.3.1)代码增加 cache 支持。这个其实要看使用情况。这个又是一门学问。需要有针对性的考虑是否可以用cache,用那种cache 算法。- 代码比较复杂了
2.4)使用牛刀,比如 nosql 等 - 这个需要很多安装维护工作,代码的改动,和学习
新框架,都需要大量时间。

欢迎补充。

w
walkrandom

弄块SSD,120G的
把value写到ssd,filename就是key
然后把key load到java就可以了,
需要什么就读硬盘就行

kv database都是这样的
但你没必要用kv database
半小时时间max

s
sanwadie

70B 个文件,目录得有多大,查找一次文件需要多长时间?至少目录要hash一下,否则没法用

【 在 walkrandom (walkrandom) 的大作中提到: 】
: 弄块SSD,120G的
: 把value写到ssd,filename就是key
: 然后把key load到java就可以了,
: 需要什么就读硬盘就行
: kv database都是这样的
: 但你没必要用kv database
: 半小时时间max

n
netghost

第一要做的事情是,别用java。
【 在 nowwhat2012 (Judgment  day) 的大作中提到: 】
: 在编一个Java程序。需要生成一个很大的HashMap(这个生成的操作只做一次)。 然后
: 多次查询这个HashMap。
: 现在发现这个HashMap很大, 初算了一下估计有70G.
: 在用Java 直接运行程序的时候出现java.lang.OutOfMemoryError: Java heap space: 在命令行用 -Xmx65536m 后Java 报错OpenJDK 64-Bit Server VM warning: INFO:
os:
: space' (errno=12)
: 机器的OS是Linux Mint 19.2 Tina;memory size 是32G
: 大伙碰到过这个情形吗?这个怎么解决?
: 谢谢!

s
silverhawk

哪些KV store用的是K存在内存?我理解很多都是LSM tree。内存是inmemory table
【 在 walkrandom (walkrandom) 的大作中提到: 】
: 弄块SSD,120G的
: 把value写到ssd,filename就是key
: 然后把key load到java就可以了,
: 需要什么就读硬盘就行
: kv database都是这样的
: 但你没必要用kv database
: 半小时时间max

w
walkrandom

in memory 和 kv db不一样
LSM tree最后还是hit hard disk

【 在 silverhawk (silverhawk) 的大作中提到: 】
: 哪些KV store用的是K存在内存?我理解很多都是LSM tree。内存是inmemory table

n
netghost

文件系统overhead太高了。如果你只是要个kv,不是特别理想。
【 在 walkrandom (walkrandom) 的大作中提到: 】
: in memory 和 kv db不一样
: LSM tree最后还是hit hard disk

c
cxfcxf

存硬盘 然后索引健在内存里
l
lauxp

做成多层次的hash?

有人上面讲LSM,那是用来解决重复写index到硬盘低效的,楼主这个是写一次然后
immutable,帮助不大