代码之家  ›  专栏  ›  技术社区  ›  Boune

如何提高Java应用程序的内存效率?

  •  17
  • Boune  · 技术社区  · 17 年前

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

    • 使用正确的数据类型
      • 避免使用java.lang.String来表示其他数据类型
      • 如果预先知道值,则使用枚举
      • 使用对象池
      • String.intern()(好主意?)
    • 仅加载/保留所需的对象

    编辑:

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

    用例

    • 在内存中加载一个巨大的csv文件(转换为POJO)
    • 使用hibernate从数据库中检索数百万条记录

    答覆摘要:

    • 使用飞锤模式
    • 抄写
    • 使用3个大小为10M的数组(或其他数据结构)是否比加载具有3个属性的10M对象更有效?(操作数据可能会很痛苦,但如果你真的内存不足…)
    11 回复  |  直到 5 年前
        1
  •  20
  •   Peter Lawrey    17 年前

    我建议您使用内存分析器,查看内存消耗的位置,并对其进行优化。如果没有定量的信息,你最终可能会改变一些事情,这些事情要么没有效果,要么实际上会让事情变得更糟。

    您可以考虑更改数据的表示形式,尤其是在对象很小的情况下。 例如,可以将数据表表示为一系列列,每列具有对象数组,而不是每行一个对象。如果不需要表示单个行,那么这可以为每个对象节省大量开销。e、 g.具有12列和10000000行的表可以使用12个对象(每列一个),而不是1000万个对象(每行一个)

        2
  •  18
  •   Community Mohan Dere    9 年前

    你没有说你想储存什么样的物品,所以很难提供详细的建议。然而,一些(非排他性)方法(无特定顺序)是:

    • 使用 flyweight pattern 无论什么地方 可能的
    • 缓存到磁盘。有 numerous 缓存解决方案 JAVA
    • 实习是个好主意。看见 here String.intern(),以及 围绕其适用性展开辩论。
    • 利用 soft weak 按需重新创建/重新加载。看见 here 关于如何使用软 使用缓存技术的引用。

    更多地了解所存储对象的内部结构和生命周期将得到更详细的答案。

        3
  •  11
  •   krosenvold    17 年前

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

    嗯,而且,如果只有数百万个对象,我想我会选择一个像样的64位虚拟机和大量ram;)

        4
  •  4
  •   kohlerm    17 年前

    普通的“探查器”对您帮助不大,因为您需要对所有“活动”对象进行概述。您需要堆转储分析器。我推荐 Eclipse Memory analyzer .

    检查您是否可以应用flightweight、copyonwrite、惰性初始化等模式(google将是您的朋友)。

        5
  •  3
  •   rado    15 年前

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

    Building Memory-efficient Java Applications: Practices and Challenges

        6
  •  2
  •   Alex Miller    17 年前

    您可以只在内存中存储较少的对象。:)使用溢出到磁盘的缓存,或者使用Terracotta对堆进行集群(这是虚拟的),从而允许将未使用的部分从内存中清除,并透明地返回到内存中。

        7
  •  1
  •   urmalp    17 年前

    java memory profiler )80%的时候,我们忽略的例行程序中存在一些问题。此外,集合类更容易发生内存泄漏。

        8
  •  1
  •   David Plumpton    17 年前

    如果您有数百万个整数和浮点数等,那么请查看您的算法是否允许在基元数组中表示数据。这意味着每次垃圾收集的引用更少,CPU成本更低。

        9
  •  0
  •   Stephan Eggermont    17 年前

    一个奇特的方法是:将大部分数据压缩到ram中。仅展开当前工作集。如果您的数据具有良好的局部性,则可以很好地工作。

    使用更好的数据结构。java中的标准集合相当占用内存。

    [什么是更好的数据结构]

    • 如果您查看集合的源代码,就会发现如果您限制自己访问集合的方式,就可以为每个元素节省空间。
    • 集合句柄增长的方式不适合大型集合。复制太多了。对于大型集合,您需要一些基于块的算法,如btree。
        10
  •  0
  •   Michael Borgwardt    17 年前

    花一些时间熟悉和调整 VM command line options

        11
  •  0
  •   pramodc84    16 年前
    1. Assign null 对所有人的价值 variables no longer 习惯于因此 make it available for Garbage collection .
    2. De-reference the collections
        12
  •  0
  •   Saurabh    6 年前

    1) 尽可能使用正确的数据类型

    Class Person {
     int age;
     int status;
    }
    

    在这里,我们可以在发送Person对象时使用以下变量来节省内存

    class Person{
      short age;
      byte status;
    }
    

    2) 而不是返回新的ArrayList<&燃气轮机;(); 从方法中,可以使用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