您如何优化具有大量(数百万)长寿命对象的应用程序的堆尺寸使用情况? (大型缓存,从数据库中加载大量记录)

  • 使用正确的数据类型
    • 避免Java.lang.String表示其他数据类型
  • 避免重复的对象
    • 如果预先知道这些值,请使用枚举
    • 使用对象池
    • string.intern()(好主意?)
  • 加载/仅保留您需要的对象

我正在寻找一般编程或Java特定答案。没有时髦的编译器开关。

编辑:

优化可以在堆中出现数百万次的POJO的内存表示。

用例

  • 在内存中加载巨大的CSV文件(转换为Pojos)
  • 使用Hibernate从数据库中检索数百万个记录

答案简历:

  • 使用轻量级图案
  • 复制写
  • 与其加载3个属性的10m对象,不如将3个数组(或其他数据结构)的大小为10m更有效? (可能是操纵数据的痛苦,但是如果您真的缺乏记忆...)
有帮助吗?

解决方案

您不会说您要存储哪种对象,因此很难提供详细的建议。但是,某些(不是独家)的方法,没有特别的顺序:

  • 用一个 轻量级图案 尽可能。
  • 缓存到光盘。有很多的 Java的缓存解决方案。
  • 关于string.intern是否是个好主意,存在一些争论。看这里 对于一个问题。 string.intern(),以及围绕其适用性的辩论数量。
  • 利用 柔软的 或者 虚弱的引用您可以按需重新创建/重新加载的数据。看这里 有关如何使用缓存技术使用软引用。

了解您存储的对象的内部和寿命的更多信息将导致更详细的答案。

其他提示

我建议您使用内存剖面,查看内存的消耗何方并优化。如果没有定量信息,您最终可能会改变任何没有效果或实际上使情况变得更糟的事情。

您可以查看更改数据的表示形式,ESP如果您的对象很小。例如,您可以将数据表表示为一系列列,每个列的对象数组,而不是每行一个对象。如果您不需要表示单个行,则可以为每个对象节省大量的开销。例如,一张具有12列和10,000,000行的表可以使用12个对象(每列1个),而不是1000万(每行1个)

确保对象模型的良好正常化,不要重复值。

哎呀,如果只有数百万个物体,我认为我只需要去一个不错的64位VM和很多RAM;)

普通的“剖道师”对您没有太大帮助,因为您需要对所有“实时”对象的概述。您需要堆转储分析仪。我推荐 Eclipse内存分析仪.

从字符串开始检查是否重复的对象。检查您是否可以应用诸如Flighteweight,CopyOnwrite,Lazy初始化(Google将是您的朋友)等模式。

看一下从这里链接的此演示文稿。它列出了通用Java对象和原语的内存使用,并帮助您了解所有额外的内存去向。

建立记忆效率的Java应用程序:实践和挑战

You could just store fewer objects in memory. :) Use a cache that spills to disk or use Terracotta to cluster your heap (which is virtual) allowing unused parts to be flushed out of memory and transparently faulted back in.

I want to add something to the point Peter alredy made(can't comment on his answer :() it's always better to use a memory profiler(check java memory profiler) than to go by intution.80% of time it's routine that we ignore has some problem in it.also collection classes are more prone to memory leaks.

If you have millions of Integers and Floats etc. then see if your algorithms allow for representing the data in arrays of primitives. That means fewer references and lower CPU cost of each garbage collection.

A fancy one: keep most data compressed in ram. Only expand the current working set. If your data has good locality that can work nicely.

Use better data structures. The standard collections in java are rather memory intensive.

[what is a better data structure]

  • If you take a look at the source for the collections, you'll see that if you restrict yourself in how you access the collection, you can save space per element.
  • The way the collection handle growing is no good for large collections. Too much copying. For large collections, you need some block-based algorithm, like btree.

Spend some time getting acquainted with and tuning the VM command line options, especially those concerning garbage collection. While this won't change the memory used by your objects, it can have a big impact on performance with memory-intensive apps on machines with a lot of RAM.

  1. Assign null value to all the variables which are no longer used. Thus make it available for Garbage collection.
  2. De-reference the collections once usage is over, otherwise GC won't sweep those.
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top