如何优化具有大量(数百万)长寿命对象的应用程序的堆大小使用? (大缓存,从数据库加载大量记录)
我正在寻找通用编程或Java特定答案。没有时髦的编译器开关。
编辑:
优化可在堆中出现数百万次的POJO的内存表示。
用例
简历回复:
答案 0 :(得分:20)
我建议您使用内存分析器,查看内存消耗的位置并对其进行优化。如果没有定量信息,你最终可能会改变那些无效或实际上让事情变得更糟的事情。
您可以查看更改数据的表示形式,尤其是对象很小的情况。 例如,您可以将数据表表示为一系列列,每列包含对象数组,而不是每行一个对象。如果您不需要表示单个行,这可以为每个对象节省大量开销。例如一个包含12列和10,000,000行的表可以使用12个对象(每列一个)而不是1000万个(每行一个)
答案 1 :(得分:17)
您没有说要存储哪种对象,因此提供详细建议有点困难。然而,一些(非排他性)方法,无特定顺序,是:
了解有关您正在存储的对象的内部和生命周期的更多信息,可以得到更详细的答案。
答案 2 :(得分:11)
确保对象模型的良好规范化,不要重复值。
嗯,如果它只有数百万个对象我认为我只需要一个体面的64位虚拟机和大量的内存;)答案 3 :(得分:4)
普通的“分析器”对您没有多大帮助,因为您需要概览所有“实时”对象。你需要堆转储分析器。我推荐Eclipse Memory analyzer。
从字符串开始检查重复的对象。 检查您是否可以应用诸如flightweight,copyonwrite,延迟初始化等模式(google将成为您的朋友)。
答案 4 :(得分:3)
看一下这里链接的演示文稿。它列出了常见java对象和基元的内存使用,并帮助您了解所有额外内存的去向。
Building Memory-efficient Java Applications: Practices and Challenges
答案 5 :(得分:2)
您可以在内存中存储更少的对象。 :)使用溢出到磁盘的缓存或使用Terracotta集群堆(这是虚拟的)允许未使用的部分从内存中刷新并透明地重新插入。
答案 6 :(得分:1)
我想在彼得·阿雷迪所做的事情上添加一些东西(不能评论他的回答:()使用内存探查器(检查java memory profiler)总比使用直觉更好.80%我们忽略的例程在其中存在一些问题。而且集合类更容易发生内存泄漏。
答案 7 :(得分:1)
如果你有数百万的整数和浮点数等,那么看看你的算法是否允许用基元数组表示数据。这意味着每个垃圾收集的引用更少,CPU成本更低。
答案 8 :(得分:0)
一个奇特的:保持大多数数据压缩为ram。仅展开当前工作集。如果您的数据具有可以很好地工作的良好位置。
使用更好的数据结构。 java中的标准集合相当占用内存。
[什么是更好的数据结构]
答案 9 :(得分:0)
花一些时间熟悉和调整VM command line options,尤其是那些与垃圾收集有关的问题。虽然这不会改变对象使用的内存,但它会对具有大量RAM的计算机上的内存密集型应用程序产生很大影响。
答案 10 :(得分:0)
Assign null
对所有使用variables
的{{1}}的值。因此no longer
。make it available for Garbage collection
一旦使用结束,否则GC不会扫描那些。答案 11 :(得分:0)
1)尽可能使用正确的数据类型
Class Person {
int age;
int status;
}
在这里,我们可以在发送Person对象时使用以下变量来节省内存
class Person{
short age;
byte status;
}
2)而不是返回新的ArrayList <>();从method,您可以使用Collection.emptyList(),它将仅包含一个元素,而不是默认的10个元素。
例如
public ArrayList getResults(){
.....
if(failedOperation)
return new ArrayList<>();
}
//Use this
public ArrayList getResults(){
if(failedOperation)
return Collections.emptyList();
}
3)尽可能在方法中移动对象的创建,而不是静态声明,因为对象的字段将存储在堆栈中,而不是堆中
4)使用protobuf,thrift,avro,messagepack之类的二进制格式代替json或XML来减少相互通信