【问题标题】:Java Large Object storage - Protocol buffers, MemoryMappedFilesJava 大对象存储 - 协议缓冲区、MemoryMappedFiles
【发布时间】:2014-09-06 07:00:37
【问题描述】:

我们有 Java 程序,具有树结构、ArrayList 和 MultiMaps 的大对象。

我遇到的问题是,我们已经分配了 3GB 的堆内存,但它仍然没有空间。

我想知道这里是否有人可以建议一种将这些对象存储在堆外的方法,并根据每个处理调用的需要将数据块读回 java 程序。由于其他原因,我有兴趣将它们存储在文件中而不是数据库中。

我遇到了“内存映射文件”,有人在相关问题上建议“协议缓冲区”,目前这些对我来说是陌生的概念,想知道是否有简单的方法。我也找不到关于这两个概念的好例子。

非常感谢您对此提供的帮助。

性能是非常重要的考虑因素,我知道 JVM 堆分配,但我不希望增加 JVM 堆大小。

【问题讨论】:

  • 听起来像是 XY 问题。认为我错了吗?提供有关“大对象”的详细信息以及您需要如何使用它们。向我们展示您为什么要探索像内存映射文件这样的奇特解决方案。
  • 我已经用Java把数据放到了一个内存映射文件中,但是缺点是里面存储的数据不是Java对象——它只是看起来像一个大字节数组。
  • @Andreas,感谢您的回复。我们有我们读入 Java 的后端表数据,并根据一些逻辑将这些数据转换为 Java 数据结构 - 树数据结构、对象的 ArrayList 和 MultiMaps。我有 Java 逻辑,可以从这些对象和数据结构中读取数据,并根据他们的输入处理用户请求。如果还不清楚,我真的很抱歉。希望我能提供更多细节。我没有理由去寻求异国情调的解决方案。我会接受你的任何建议。
  • @antlersoft,人类不会读取文件内容。它将读取数据的同一 Java 程序。您能指导我在哪里可以找到更多详细信息和主要示例吗?

标签: java performance jvm protocol-buffers memory-mapped-files


【解决方案1】:

您可以考虑将数据存储在Chronicle Map 之类的位置。这使用了堆外内存,并且可以在不产生任何垃圾的情况下进行存储和访问。这允许您减少堆大小,但您仍然需要购买合理的内存。我建议您考虑使用至少 32 GB 的内存,无论您是在堆上还是在堆外使用较大的数据集。

我没有理由去寻求奇异的解决方案

在这种情况下,请坚持使用堆上解决方案。您可以花 200 美元左右购买 16 GB 内存。

我不是在寻找增加 JVM 堆大小。

问问自己你愿意投入多少时间/金钱来避免增加堆。你当然可以这样做,但为了节省 4 GB,我不会花一天时间在这上面。节省 40 GB 或 400 GB 或 4 TB 就是另一回事了。

【讨论】:

  • 嗨彼得,非常感谢您的回复。我会检查你的建议。而且,这不是我个人的工作,我可以轻松获得 16GB 内存。这是我的办公室项目,要获得这么多内存并不容易,相信我。
  • @bluzeee 是的,有些地方会很乐意浪费大量时间/金钱来避免在硬件上花钱。
【解决方案2】:

Protocol Buffers 不适用于内存映射文件,因为文件包含编码数据,必须先解码才能使用它。此解码步骤生成堆对象。如果您将文件拆分为许多小消息,您可以在需要时按需解码这些小消息,然后立即丢弃解码后的版本,您也许可以将 Protobufs 与内存映射文件一起使用。但是,如果您不小心,可能会浪费大量时间重复解码相同的数据。

Cap'n Proto 是一种较新的格式,与 Protocol Buffers 非常相似,但专门设计用于处理内存映射文件。磁盘格式的设计使其可以在没有解码步骤的情况下就地使用。我们正在开发一个Java version,它应该可以在几周内投入生产使用。

(披露:我是 Cap'n Proto 的创建者,之前也是 Google Protocol Buffers 的维护者。)

【讨论】:

  • 感谢您的回复。
【解决方案3】:

您也许可以使用来自Guava 的不可变集合,它们通常不太占用内存。

如果字符串占用了您相当多的内存,您也许可以使用String.intern

如果您有很多盒装图元,使用 trove4j 可以节省很多。

你可以做一些小技巧,比如使用更小的数据类型等等......

但你真的应该让你的办公室获得更多内存,然后再将时间浪费在拥有与智能手机一样多 RAM 的计算机上!

【讨论】:

  • 感谢您的回复。我检查了 Trove 和 HPPC,但我有对象而不是原语。我还检查了巨大的集合,根据我检查的内容,我需要自定义接口,但我使用的是数组列表和集合对象的映射(不仅仅是字符串),它们是内存的主要消费者。我终于选择了 Fastutil,但没有看到任何内存节省,不确定我是否做错了什么。我必须进一步检查。
猜你喜欢
  • 2013-09-01
  • 2019-03-02
  • 1970-01-01
  • 2010-11-29
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
相关资源
最近更新 更多