简体   繁体   English

Java Native Memory 比堆快吗?

[英]Is Java Native Memory Faster than the heap?

I'm exploring options to help my memory-intensive application, and in doing so I came across Terracotta's BigMemory .我正在探索帮助我的内存密集型应用程序的选项,并且在这样做时我遇到了 Terracotta 的BigMemory From what I gather, they take advantage of non-garbage-collected, off-heap "native memory," and apparently this is about 10x slower than heap-storage due to serialization/deserialization issues.据我所知,他们利用了非垃圾收集的堆外“本机 memory”,由于序列化/反序列化问题,这显然比堆存储慢 10 倍。 Prior to reading about BigMemory, I'd never heard of "native memory" outside of normal JNI.在阅读 BigMemory 之前,我从未听说过普通 JNI 之外的“本机内存”。 Although BigMemory is an interesting option that warrants further consideration, I'm intrigued by what could be accomplished with native memory if the serialization issue could be bypassed.尽管 BigMemory 是一个值得进一步考虑的有趣选项,但如果可以绕过序列化问题,我对使用原生 memory 可以完成的工作很感兴趣。

Is Java native memory faster (I think this entails ByteBuffer objects?) than traditional heap memory when there are no serialization issues (for instance if I am comparing it with a huge byte[] )? Java 本机 memory 是否比传统堆 memory 更快(我认为这需要ByteBuffer对象?)当没有大的序列化问题时(例如byte[] Or do the vagaries of garbage collection, etc. render this question unanswerable?还是垃圾收集等的变幻莫测使这个问题无法回答? I know "measure it" is a common answer around here, but I'm afraid I would not set up a representative test as I don't yet know enough about how native memory works in Java.我知道“测量它”是一个常见的答案,但恐怕我不会设置一个有代表性的测试,因为我还不太了解原生 memory 在 Java 中的工作原理。

Direct memory is faster when performing IO because it avoid one copy of the data.直接 memory 在执行 IO 时更快,因为它避免了数据的一份副本。 However, for 95% of application you won't notice the difference.但是,对于 95% 的应用程序,您不会注意到差异。

You can store data in direct memory, however it won't be faster than storing data POJOs.您可以将数据直接存储在 memory 中,但是它不会比存储数据 POJO 更快。 (or as safe or readable or maintainable) If you are worried about GC, try creating your objects (have to be mutable) in advance and reuse them without discarding them. (或安全、可读或可维护)如果您担心 GC,请尝试提前创建对象(必须是可变的)并重用它们而不丢弃它们。 If you don't discard your objects, there is nothing to collect.如果你不丢弃你的物品,就没有什么可收集的。


Is Java native memory faster (I think this entails ByteBuffer objects?) than traditional heap memory when there are no serialization issues (for instance if I am comparing it with a huge byte[])? Java 本机 memory 是否比传统堆 memory 更快(我认为这需要 ByteBuffer 对象?)当没有巨大的序列化问题时(例如)?

Direct memory can be faster than using a byte[] if you use use non bytes like int as it can read/write the whole four bytes without turning the data into bytes.如果您使用像int这样的非字节,直接 memory 可以比使用 byte[] 更快,因为它可以读取/写入整个四个字节而无需将数据转换为字节。 However it is slower than using POJOs as it has to bounds check every access.但是它比使用 POJO 慢,因为它必须对每次访问进行边界检查。

Or do the vagaries of garbage collection, etc. render this question unanswerable?还是垃圾收集等的变幻莫测使这个问题无法回答?

The speed has nothing to do with the GC.速度与GC无关。 The GC only matters when creating or discard objects. GC 仅在创建或丢弃对象时才重要。

BTW: If you minimise the number of object you discard and increase your Eden size, you can prevent even minor collection occurring for a long time eg a whole day.顺便说一句:如果您最小化您丢弃的 object 的数量并增加您的 Eden 大小,您可以防止长时间(例如一整天)发生甚至很小的收集。

The point of BigMemory is not that native memory is faster, but rather, it's to reduce the overhead of the garbage collector having to go through the effort of tracking down references to memory and cleaning it up. BigMemory 的重点不是原生 memory 更快,而是通过跟踪对 ZCD69B4957F06CD829D7BF3D61980 的引用并清理它来减少 go 的垃圾收集器的开销。 As your heap size increases, so do your GC intervals and CPU commitment.随着堆大小的增加,您的 GC 间隔和 CPU 承诺也会增加。 Depending upon the situation, this can create a sort of "glass ceiling" where the Java heap gets so big that the GC turns into a hog, taking up huge amounts of processor power each time the GC kicks in. Also, many GC algorithms require some level of locking that means nobody can do anything until that portion of the GC reference tracking algorithm finishes, though many JVM's have gotten much better at handling this.根据具体情况,这可能会产生一种“玻璃天花板”,其中 Java 堆变得如此之大,以至于 GC 变成了一只猪,每次 GC 启动时都会占用大量的处理器资源。此外,许多 GC 算法需要某种程度的锁定意味着在 GC 引用跟踪算法的那部分完成之前没有人可以做任何事情,尽管许多 JVM 在处理这方面已经做得更好。 Where I work, with our app server and JVM's, we found that the "glass ceiling" is about 1.5 GB.在我工作的地方,使用我们的应用服务器和 JVM,我们发现“玻璃天花板”大约是 1.5 GB。 If we try to configure the heap larger than that, the GC routine starts eating up more than 50% of total CPU time, so it's a very real cost.如果我们尝试将堆配置得比这个大,GC 例程开始占用超过 50% 的总 CPU 时间,所以这是一个非常实际的成本。 We've determined this through various forms of GC analysis provided by our JVM vendor.我们通过我们的 JVM 供应商提供的各种 forms GC 分析确定了这一点。

BigMemory, on the other hand, takes a more manual approach to memory management.另一方面,BigMemory 采用更手动的方法来管理 memory。 It reduces the overhead and sort of takes us back to having to do our own memory cleanup, as we did in C, albeit in a much simpler approach akin to a HashMap.它减少了开销,并且让我们不得不重新进行自己的 memory 清理,就像我们在 C 中所做的那样,尽管采用类似于 Z063A5BC470661C31C7909BCE1B7E9 的更简单的方法。 This essentially eliminates the need for a traditional garbage collection routine, and as a result, we eliminate that overhead.这基本上消除了对传统垃圾收集例程的需求,因此,我们消除了这种开销。 I believe that the Terracotta folks used native memory via a ByteBuffer as it's an easy way to get out from under the Java garbage collector.我相信 Terracotta 的人通过 ByteBuffer 使用原生 memory,因为这是从 Java 垃圾收集器下脱身的简单方法。

The following whitepaper has some good info on how they architected BigMemory and some background on the overhead of the GC: http://www.terracotta.org/resources/whitepapers/bigmemory-whitepaper .以下白皮书提供了一些关于他们如何构建 BigMemory 以及 GC 开销的一些背景信息: http://www.terracotta.org/resources/whitepapers/bigmemory-whitepaper

I'm intrigued by what could be accomplished with native memory if the serialization issue could be bypassed.如果可以绕过序列化问题,我对本机 memory 可以完成的工作很感兴趣。

I think that your question is predicated on a false assumption.我认为您的问题是基于错误的假设。 AFAIK, it is impossible to bypass the serialization issue that they are talking about here. AFAIK,不可能绕过他们在这里谈论的序列化问题。 The only thing you could do would be to simplify the objects that you put into BigMemory and use custom serialization / deserialization code to reduce the overheads.您唯一能做的就是简化放入 BigMemory 的对象,并使用自定义序列化/反序列化代码来减少开销。

While benchmarks might give you a rough idea of the overheads, the actual overheads will be very application specific.虽然基准测试可能会让您大致了解开销,但实际开销将是非常特定于应用程序的。 My advice would be:我的建议是:

  • Only go down this route if you know you need to.如果你知道你需要的话,只有 go 沿着这条路线走。 (You will be tying your application to a particular implementation technology.) (您将把您的应用程序与特定的实现技术联系起来。)

  • Be prepared for some intrusive changes to your application if the data involved isn't already managed using as a cache.如果所涉及的数据尚未作为缓存进行管理,请准备好对应用程序进行一些侵入性更改。

  • Be prepared to spend some time in (re-)tuning your caching code to get good performance with BigMemory.准备好花一些时间(重新)调整缓存代码,以获得 BigMemory 的良好性能。

  • If your data structures are complicated, expect a proportionately larger runtime overheads and tuning effort.如果您的数据结构很复杂,预计运行时开销和调优工作会相应增加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM