内存消耗java.util.Date vs java.time.LocalDate vs org.joda.time.DateTime

时间:2014-07-24 15:14:07

标签: java datetime memory java-8

我想知道

的内存消耗情况
  • java.util.Date
  • java.time.LocalDate
  • org.joda.time.DateTime

我需要创建一堆具有一些Dates的对象,今天它们的时间戳是长的但是这不太好并且在另一侧创建CPU负载因为我需要日期。

所以我的问题是:有没有统计数据? 如何测量这些东西呢?

4 个答案:

答案 0 :(得分:2)

我不担心,你需要数以百万计的物品来真正改变服务器。

但是如果你真的想知道,你可以查看实现以查看每个对象的字段,每个父对象的字段等以及每个引用对象的字段)。您可以添加每个字段使用的字节数+对象引用的大小(4或8个字节,具体取决于JVM)以及Java规范中描述的填充。

或者您可以使用java.sizeOf等第三方库来为您执行此操作。

但是快速浏览一下你问过的课程的代码,这里是字段:

<强>日期:

private transient long fastTime;

/*
 * If cdate is null, then fastTime indicates the time in millis.
 * If cdate.isNormalized() is true, then fastTime and cdate are in
 * synch. Otherwise, fastTime is ignored, and cdate indicates the
 * time.
 */
private transient BaseCalendar.Date cdate;

long +对具有自己的字段等的其他类的引用。但是,经过大量代码阅读后,cdate几乎是null所以我们只需计算大小对象引用(为null)我认为当使用32位或64位时,使用压缩的Ops尝试使用4字节引用时,不会超出24字节填充的对象大小尽可能代替8。 (我认为这是Java 8的默认设置)所以我们可以忽略它。

<强> LOCALDATE:

/**
 * The year.
 */
private final int year;
/**
 * The month-of-year.
 */
private final short month;
/**
 * The day-of-month.
 */
private final short day;

因此int+short+shortlong的大小相同,但您必须考虑到您保留的每个LocalDate引用的内存。

<强>日期时间:

 private long iMillis;


 private Chronology iChronology;

对于占用内存的其他对象,也是long +对象引用。

使用SizeOf

当我在64位Java 8 JVM上创建每个对象的实例并在它们上使用java.sizeOf时,我得到了以下内存大小(以字节为单位):

javaDate = 24    
localDate = 24

dateTime = 16928

正如你所看到的,jodatime在其所有支持类中占用了大量内存。当你有其他实例的时候,大部分都会重复使用。

因此,如果他们没有被包裹在课堂中,我会继续使用你的long。但是,如果您将long包裹在课堂中,或者甚至使用LongLocalDate似乎最好,因为它具有相同的内存量以及所有用于转换的支持类/时区等我不会使用Date,因为该类是可变的,应该被视为已弃用。

答案 1 :(得分:1)

  1. 效率最高;以长值存储:8个字节(当它作为参数传递时,它是不可变的)

  2. Java.util.Date
    VM 64位:12为对象+8为长值+ 4为ref为BaseCal.Date = 24字节
    Sun VM 32位:8 + 8 + 4 = 20 + 4填充= 24​​字节
    (不可推荐,因为没有任何优势,是可变的,需要更多的记忆)

    有实现(IBM Embedded Java,其中Date只有一个字段)(最小16字节)


  3. LOCALDATE VM 64位:12 + 4 + 2 + 2 = 20 + 4填充= 24​​字节
    VM 32位:8 + 4 + 2 + 2 = 16字节;
    在android Dalvik:12 + 4 + 4 + 4 = 24字节

  4. joda DateTime
    VM 64位:12 + 8 + 4用于参考年表:= 24个字节
    VM 32位:8 + 8 + 4用于参考年表+ 4填充= 24​​字节

  5. 如何衡量这些事情呢? 在Sun VM上,您可以使用MAT,它使用Sun VM的特殊功能。 (见Szymon Krawczyk的答案) 在其他虚拟机上,它很难衡量,我见过的任何代码(MemoryTestBench基于堆大小,gc调用等)在某些情况下都会失败,从而导致负内存消耗。

    最正确的方法是自己计算:

    取决于VM,空对象需要8字节Sun VM 32或12 Sun VM64 + Dalvik +对象大小始终填充到8字节的下一个倍数。

    <强>字段
    参考字段需要4个字节。 int:4个字节,
    长8,
    短期2(或Dalvik上的4),
    布尔1字节(太阳),4字节Dalvik;

    数组是一个对象+一个int字段(array.length)= 16字节,但Dalvik除外,因为奇怪的原因它需要20个字节(如果没有elemens则为+ 4填充)= 24

答案 2 :(得分:1)

根据joda-time,他们提供了处理日期的最佳方式:

http://www.joda.org/joda-time/ http://www.joda.org/joda-time/faq.html

  

Joda-Time已经创建,可以从根本上改变Java中的日期和时间处理。 JDK类日期和日历的设计非常糟糕,有很多错误并且具有奇怪的性能影响。以下是开发和使用Joda-Time的一些原因:

  • 易于使用。由于缺乏简单的方法,日历使得访问“正常”日期变得困难。 Joda-Time有简单的字段访问器,如getYear()或getDayOfWeek()。
  • 易于扩展。 JDK通过Calendar的子类支持多个日历系统。这很笨重,实际上编写另一个日历系统非常困难。 Joda-Time通过基于Chronology类的可插拔系统支持多个日历系统。
  • 全面的功能集。该库旨在提供日期时间计算所需的所有功能。它已经提供了开箱即用的功能,例如支持奇怪的日期格式,这些格式难以与JDK一起复制。
  • 最新的时区计算。时区实施基于公共tz数据库,该数据库每年更新几次。新的Joda-Time版本包含对此数据库所做的所有更改。如果之前需要更改,则手动更新区域数据很容易。
  • 日历支持。该库目前提供8个日历系统。将来会增加更多内容。
  • 轻松实现互操作性。库内部使用的毫秒时刻与JDK相同,与其他常用时间表示相似。这使得互操作性变得简单,Joda-Time带有开箱即用的JDK互操作性。
  • 更好的性能特征。日历具有奇怪的性能特征,因为它会在意外时刻重新计算字段。 Joda-Time只对正在访问的字段进行最小化计算。
  • 良好的测试覆盖率。 Joda-Time拥有一整套开发人员测试,可确保图书馆的质量。
  • 完整文档。有完整的用户指南,其中提供了概述并介绍了常见的使用方案。 javadoc非常详细,涵盖了API的其余部分。
  • 成熟度。该库自2002年以来一直处于积极开发阶段。虽然它通过添加新功能和错误修复而不断改进,但它是一个成熟可靠的代码库。现在有许多相关项目可供使用。
  • 开源。 Joda-Time根据业务友好的Apache许可版本2.0获得许可。

根据个人经验,我同意他们的看法。但是,您可以在运行应用程序时使用 jvisualvm (jdk / bin)分析工具更好地分析它。

答案 3 :(得分:0)

我可以发表评论,但就内存使用而言,你可以通过这样做获取运行应用程序的内存转储(堆转储): jmap -dump:format=b,file=cheap.bin <pid>
然后安装MAT当然如果您正在使用ECLIPSE在eclipse中打开该文件并比较对象大小。 我用它来查找我的web应用程序中使用servlet和Tomcat服务器的内存泄漏 这真的很有用

但是如果你对这个问题不感兴趣,可以看一下get OS-level system information