Java 本机内存比堆快吗?
我正在探索帮助我的内存密集型应用程序的选项,在此过程中我遇到了 Terracotta 的 BigMemory。据我所知,它们利用了非垃圾收集的堆外“本机内存”,并且显然由于序列化/反序列化问题,这比堆存储慢了大约 10 倍。在阅读 BigMemory 之前,我从未听说过普通 JNI 之外的“本机内存”。尽管 BigMemory 是一个有趣的选项,值得进一步考虑,但我对如果可以绕过序列化问题可以使用本机内存实现什么感兴趣。
当不存在序列化问题时(例如,如果我将其与巨大的 byte[]ByteBuffer
对象?)代码>)?或者垃圾收集等变幻莫测的行为是否使这个问题无法回答?我知道“测量它”是这里的一个常见答案,但恐怕我不会设置代表性测试,因为我还不太了解 Java 中的本机内存如何工作。
I'm exploring options to help my memory-intensive application, and in doing so I came across Terracotta's 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. Prior to reading about BigMemory, I'd never heard of "native memory" outside of normal 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.
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[]
)? 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
直接内存在执行 IO 时速度更快,因为它避免了数据的一份副本。然而,对于 95% 的应用程序,您不会注意到差异。
您可以将数据存储在直接内存中,但它不会比存储数据 POJO 更快。 (或者安全、可读或可维护)如果您担心 GC,请尝试提前创建对象(必须是可变的)并重用它们而不丢弃它们。如果你不丢弃你的物品,就没有什么可以收集的。
如果您使用像
int
这样的非字节,直接内存可能比使用 byte[] 更快,因为它可以读取/写入整个四个字节,而无需将数据转换为字节。然而,它比使用 POJO 慢,因为它必须对每次访问进行边界检查。
速度与GC无关。 GC 仅在创建或丢弃对象时起作用。
顺便说一句:如果您最大限度地减少丢弃的对象数量并增加 Eden 大小,则可以防止长时间(例如一整天)发生少量收集。
Direct memory is faster when performing IO because it avoid one copy of the data. However, for 95% of application you won't notice the difference.
You can store data in direct memory, however it won't be faster than storing data POJOs. (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. If you don't discard your objects, there is nothing to collect.
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.However it is slower than using POJOs as it has to bounds check every access.
The speed has nothing to do with the GC. The GC only matters when creating or discard objects.
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 e.g. a whole day.
BigMemory 的重点不是本机内存更快,而是减少垃圾收集器跟踪内存引用并清理内存的开销。随着堆大小的增加,GC 间隔和 CPU 占用也会增加。根据具体情况,这可能会产生一种“玻璃天花板”,其中 Java 堆变得如此之大,以至于 GC 变成了一个“猪”,每次 GC 启动时都会占用大量的处理器能力。此外,许多 GC 算法都需要某种程度的锁定意味着在 GC 引用跟踪算法的该部分完成之前没有人可以做任何事情,尽管许多 JVM 在处理这个问题上已经做得更好了。在我工作的地方,我们的应用程序服务器和 JVM 发现“玻璃天花板”约为 1.5 GB。如果我们尝试配置比这个更大的堆,GC 例程就会开始占用超过 50% 的总 CPU 时间,因此这是一个非常实际的成本。我们通过 JVM 供应商提供的各种形式的 GC 分析确定了这一点。
另一方面,BigMemory 采用更加手动的内存管理方法。它减少了开销,并且让我们不得不自己进行内存清理,就像我们在 C 中所做的那样,尽管采用的是类似于 HashMap 的更简单的方法。这基本上消除了对传统垃圾收集例程的需要,因此,我们消除了这种开销。我相信 Terracotta 人员通过 ByteBuffer 使用本机内存,因为这是摆脱 Java 垃圾收集器的简单方法。
以下白皮书提供了有关如何构建 BigMemory 的一些有用信息以及有关 GC 开销的一些背景信息:http://www.terracotta.org/resources/whitepapers/bigmemory-whitepaper。
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. As your heap size increases, so do your GC intervals and CPU commitment. 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. Where I work, with our app server and JVM's, we found that the "glass ceiling" is about 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. We've determined this through various forms of GC analysis provided by our JVM vendor.
BigMemory, on the other hand, takes a more manual approach to memory management. 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. 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.
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.
我认为你的问题是基于错误的假设。 AFAIK,不可能绕过他们在这里讨论的序列化问题。您唯一可以做的就是简化放入 BigMemory 的对象并使用自定义序列化/反序列化代码来减少开销。
虽然基准测试可能会让您对开销有一个粗略的了解,但实际开销将非常特定于应用程序。我的建议是:
只有在您知道需要时才走这条路。 (您将把您的应用程序与特定的实现技术联系起来。)
如果所涉及的数据尚未作为缓存进行管理,请准备好应对应用程序的一些侵入式更改。
准备花一些时间(重新)调整您的缓存代码以获得 BigMemory 的良好性能。
如果您的数据结构很复杂,则预计运行时开销和调整工作也会相应增加。
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. 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.
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. (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.
If your data structures are complicated, expect a proportionately larger runtime overheads and tuning effort.