在我的Spark程序中,我对分配和使用Java垃圾收集器未触及的数据感兴趣。基本上,我想像在C ++中那样自己对这些数据进行内存管理。这是使用off堆内存的好例子吗?其次,如何在Java或Scala中读取和写入堆内存。我尝试搜索示例,但找不到任何示例。
答案 0 :(得分:4)
手动内存管理是垃圾收集语言的可行优化策略。垃圾收集是已知的开销来源,可以定制算法以最小化它。例如,在选择哈希表实现时,可能更喜欢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
。
答案 1 :(得分:2)
如果您无法实现“算法效率,数据结构性能”,并且效率和性能如此重要,您可以考虑使用“sun.misc.Unsafe”。顾名思义它不安全!!!
Spark已经在project-tungsten中提到它了。
此外,您可以启动here,以便更好地理解它!
注意:Spark为应用程序的执行提供了高度并发性,并且在多台机器上最可能提供多个JVM,手动内存管理将非常复杂。 Fundamemtally spark促进了对全局共享内存的重新计算。所以,也许,您可以将部分计算的数据/结果存储在另一个商店,如HDFS / Kafka / cassandra !!!
答案 2 :(得分:0)
看看ByteBuffer.allocateDirect(int bytes)。您不需要使用内存映射文件来使用它们。
如果对象会在那里停留一段时间(即重复使用),则关闭堆可能是一个不错的选择。如果你在去的时候分配/解除分配,那就会慢一点。
不安全很酷,但它是going to be removed。可能在Java 9中。