Java内存感知缓存

发布于 2024-12-02 01:01:27 字数 404 浏览 0 评论 0原文

我正在寻找一些想法,如果有人知道的话,也许已经有了一些具体的实现,但我愿意自己编写所需的缓存。

我想要一个只缓存我配置的演出数量的缓存。与应用程序的其余部分相比,缓存部分将使用近 100% 的内存,因此我们可以将应用程序的已用内存概括为缓存大小(+垃圾)。

是否有方法可以猜测使用了多少内存?还是依靠软指针更好?软指针和始终在 jvm 内存限制的顶部运行可能会非常低效,因为需要大量 cpu 周期进行内存清理?我可以对现有对象(例如 myObject.getMemoryUsage())进行一些分析吗?

LinkedHashMap 有足够的缓存命中来满足我的目的,因此我不必编写一些策略性的缓存怪物,但我不知道如何正确解决这个内存问题。有什么想法吗?我不想让 OOME 飞到任何地方。

什么是最佳实践?

I am looking for some ideas, and maybe already some concrete implemenatation if somebody knows any, but I am willing to code the wanted cache on my own.

I want to have a cache that caches only as many gigs as I configure. In comparision to the rest of the app the cache part will use nearly 100% of memory, so we can generalize the used memory of the app beeing the cache size(+ garbage).

Are there methods for getting a guess of how much memory is used? Or is it better to rely on soft pointers? Soft pointer and running always at the top of the jvm memory limit might be very inefficent with lots of cpu cycles for memory cleaning? Can I do some analysis on existing objects, like a myObject.getMemoryUsage()?

The LinkedHashMap has enough cache hits for my purpose so I don't have to code some strategic caching monster, but I don't know how to solve this momory issue properly. Any ideas? I don't want OOME flying anywhere.

What is best pratice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

渔村楼浪 2024-12-09 01:01:27

软引用并不是一个好主意,因为它们往往会一下子变得更清晰。这意味着当您的 GC 性能受到影响时,您也必须重新构建缓存。

您可以使用 Instrumentation.getObjectSize() 获取对象的浅层大小,并使用反射获取深层大小。然而,这样做相对昂贵,而且不是您想要经常做的事情。

为什么不能将大小限制为多个对象?事实上,我会从最简单的缓存开始,只添加您真正需要的内容。

Java 中的 LRU 缓存。

编辑:跟踪您使用了多少内存的一种方法是序列化该值并将其存储为 byte[]。这可以为您提供相当精确的控制,但可能会使您的解决方案速度减慢多达 1000 倍。 (没有什么是免费的;)

SoftReference are not a great idea as they tend to be clearer all at once. This means when you get a performance hit from a GC, you also get a hit having to re-build your cache.

You can use Instrumentation.getObjectSize() to get the shallow size of an Object and use reflection to obtain a deep size. However, doing this relatively expensive and not something you want to get doing very often.

Why can't you limit the size to a number of object? In fact, I would start with the simplest cache you can and only add what you really need.

LRU cache in Java.

EDIT: One way to track how much memory you are using is to Serialize the value and store it as a byte[]. This can give you fairly precise control however can slow down your solution by up to 1000x times. (Nothing comes for free ;)

岁月无声 2024-12-09 01:01:27

我建议使用 Java 缓存系统。不过,如果您想自己动手,我不知道有什么方法可以获取内存中的对象大小。最好的选择是扩展 AbstractMap 并将值包装在 SoftReferences 中。然后您可以将 java 堆大小设置为您想要的最大大小。不过,您的实现还必须查找并清除陈旧数据。使用 JCS 可能更容易。

I would recommend using the Java Caching System. Though if you wanted to roll your own, I'm not aware of any way to get an objects size in memory. Your best bet would be to extend AbstractMap and wrap the values in SoftReferences. Then you could set the java heap size to the maximum size you wanted. Though, your implementation would also have to find and clean out stale data. It's probably easier just to use JCS.

歌入人心 2024-12-09 01:01:27

软引用的问题在于它们给垃圾收集器带来了更多的工作。虽然它不能满足您的要求,但 HBase 有一个非常有趣的策略,以防止缓存导致垃圾收集暂停:它们将缓存存储在本机内存中:

对于您的用例来说,一个好的开始是将所有数据存储在 磁盘。这可能看起来很幼稚,但由于 I/O 缓存,经常访问的数据将驻留在内存中。我强烈建议阅读 Varnish 缓存系统的这些架构说明:

The problem with SoftReferences is that they give more work to the garbage collector. Although it doesn't meet your requirements, HBase has a very interesting strategy in order to prevent the cache from contributing to the garbage collection pauses : they store the cache in native memory :

A good start for your use-case would be to store all your data on disk. It might seem naive, but thanks to the I/O cache, frequently accessed data will reside in memory. I highly recommend reading these architecture notes from the Varnish caching system :

怪我太投入 2024-12-09 01:01:27

我发现的最佳实践是如果可能的话将缓存功能委托给 Java 之外。 Java 可能擅长管理内存,但专用缓存系统不应该用于简单的 LRU 缓存。

当 GC 启动时,会产生很大的成本。EHCache

是我所知道的最流行的之一。另一个答案的Java缓存系统也很好。

但是,我通常将该工作卸载到底层函数(通常是应用程序服务器的 JPA 持久层,我让它在那里处理,这样我就不必在应用程序层处理它)。

如果您要缓存其他数据,例如 Web 请求,http://hc.apache.org/httpclient -3.x/ 也是另一个不错的候选者。

但是,请记住您还有“文件系统”,将检索到的数据写入文件系统绝对没有问题。我已经多次使用该技术来修复由于 ByteArrayOutputStreams 使用不当而导致的内存不足错误

The best practice I find is to delegate the caching functionality outside of Java if possible. Java may be good in managing memory, but at dedicated caching system should be used for anything more than a simple LRU cache.

There is a large cost with GC when it kicks in.

EHCache is one of the more popular ones I know of. Java Caching System from another answer is good as well.

However, I generally offload that work to an underlying function (usually the JPA persistence layer by the application server, I let it get handled there so I don't have to deal with it on the application tier).

If you are caching other data such as web requests, http://hc.apache.org/httpclient-3.x/ is also another good candidate.

However, just remember you also have "a file system" there's absolutely nothing wrong with writing to the file system data you have retrieved. I've used the technique several times to fix out of memory errors due to improper use of ByteArrayOutputStreams

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文