【问题标题】:How is off heap memory read/written in Java?堆外内存如何用 Java 读/写?
【发布时间】:2016-11-03 14:37:00
【问题描述】:

在我的 Spark 程序中,我对分配和使用 Java 垃圾收集器未触及的数据感兴趣。基本上,我想自己对这些数据进行内存管理,就像你在 C++ 中所做的那样。这是使用堆外内存的好例子吗?其次,您如何在 Java 或 Scala 中读取和写入堆外内存。我尝试搜索示例,但找不到任何示例。

【问题讨论】:

  • 在普通的 java 代码中不是真的,也许在 jni 上是可能的。 stackoverflow.com/questions/4404872/…
  • 刚刚也看到了。我在真正的 java 程序中从来没有这样的东西,但它应该满足你的需要。
  • 您可以在 Java 中进行自己的内存管理,方法是声明自己的队列或对象引用堆栈。只要引用被持有(即使堆栈或队列位置不再“活动”),相应的堆区域将不会被回收。警告购买者。
  • “其次,你如何在 Java 或 Scala 中读取和写入堆外内存。” ...你真的不知道。 Java 不支持任何类型的指针算术。它是一种托管语言。您使用它正是因为您想要该功能。如果你想做自己的指针数学,那么你会想要使用像 C 或者 Rust 这样的语言。

标签: java scala memory apache-spark heap-memory


【解决方案1】:

手动内存管理是垃圾收集语言的可行优化策略。垃圾收集是一种已知的开销来源,可以定制算法以将其最小化。例如,在选择哈希表实现时,可能更喜欢Open Addressing,因为它在主数组上手动分配其条目,而不是将它们处理给语言内存分配及其 GC。作为另一个示例,这里有一个Trie searcher,它将 Trie 打包成一个单字节数组,以最小化 GC 开销。类似的优化也可以用于正则表达式。

当 Java 数组用作数据的低级存储时,这种优化与 Data-oriented design 齐头并进,其中数据存储在数组中以实现更好的缓存局部性。面向数据的设计广泛用于游戏开发中,其中性能很重要。

在 JavaScript 中,这种由数组支持的数据存储是 asm.js 的重要组成部分。

Java 世界中使用的大多数垃圾收集器都充分支持数组支持的方法,因为它们会尽量避免移动大型数组。

如果您想深入挖掘,在 Linux 中,您可以在“/dev/shm”文件系统中创建一个文件。此文件系统由 RAM 支持,除非您的操作系统内存不足,否则不会刷新到磁盘。内存映射此类文件(使用FileChannel.map)是直接从操作系统获取堆外内存的好方法。 (MappedByteBuffer 操作已针对直接内存访问进行了 JIT 优化,不包括边界检查)。

如果您想更深入,那么您将不得不求助于 JNI 库来访问 C 级内存分配器 malloc

【讨论】:

    【解决方案2】:

    如果您无法实现“算法效率,数据结构性能”,并且如果效率和性能如此关键,您可以考虑使用“sun.misc.Unsafe”。顾名思义就是不安全!!!

    project-tungsten 中所述,Spark 已经在使用它。

    另外,你可以开始here,更好地理解它!!!

    注意:Spark 为应用程序的执行提供了高并发性,并且多 JVM 很可能跨多台机器,手动内存管理将非常复杂。从根本上说,spark 促进了对全局共享内存的重新计算。因此,也许,您可以将部分计算的数据/结果存储在另一个存储中,例如 HDFS/Kafka/cassandra!!!

    【讨论】:

      【解决方案3】:

      看看ByteBuffer.allocateDirect(int bytes)。您无需存储映射文件即可使用它们。

      如果对象会在此处停留一段时间(即被重复使用),则堆外可能是一个不错的选择。如果您要在执行过程中分配/取消分配它们,那会更慢。

      不安全很酷,但它是going to be removed。可能在 Java 9 中。

      【讨论】:

        猜你喜欢
        • 2018-03-23
        • 2020-04-24
        • 2021-06-07
        • 1970-01-01
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        • 2011-07-23
        • 1970-01-01
        相关资源
        最近更新 更多