繁体   English   中英

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

[英]Memory consumption java.util.Date vs java.time.LocalDate vs org.joda.time.DateTime

我想知道内存消耗

  • java.util.Date
  • java.time.LocalDate
  • org.joda.time.DateTime

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

所以我的问题是:是否有可用的统计数据? 大概如何衡量这种事情?

我不用担心,您需要数百万个对象才能真正在服务器上发挥作用。

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

或者,您可以使用第3方库(例如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位时,对象的大小超出24字节填充的范围,请使用压缩的Ops,它会尝试使用4字节引用而不是8字节引用。 (我认为这是Java 8的默认设置),因此我们可以忽略它。

本地日期:

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

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

约会时间:

 private long iMillis;


 private Chronology iChronology;

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

使用SizeOf

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

javaDate = 24    
localDate = 24

dateTime = 16928

如您所见,jodatime的所有支持类都占用大量内存。 但是,当您拥有其他实例时,其中的大部分将被重用。

因此,如果您的long不在类中,我将继续使用它们。 但是,如果您将long封装在一个类中,或者甚至使用Long ,则LocalDate似乎是最好的,因为它的内存量相同,加上所有支持的类用于转换/时区等。我不会使用Date因为该类是可变的,应该被认为已弃用。

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

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

    有实现(IBM嵌入式Java,其中Date仅具有一个字段)(这将是最少16个字节)

  3. 本地日期
    VM 64位:12 + 4 + 2 + 2 = 20 +4填充= 24​​字节
    VM 32位:8 + 4 + 2 + 2 = 16字节;
    在Android Dalvik上:12 + 4 + 4 + 4 = 24字节

  4. 乔达日期时间
    VM 64位:12 + 8 + 4,用于编年表:= 24字节
    VM 32位:8 + 8 + 4,用于编年表参考+ 4个填充= 24​​字节

大概如何衡量这种事情? 在Sun VM上,您可以使用MAT,它使用Sun VM的特殊功能。 (请参阅Szymon Krawczyk的答案)在其他VM上,它很难衡量,而且我所见的任何代码(基于堆大小的MemoryTestBench,gc调用等)在某些情况下均会失败,从而导致内存消耗为负。

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

在VM上分配空对象需要8字节的Sun VM 32或12 Sun VM64 + Dalvik +对象大小始终填充为8字节的下一个倍数。

领域
参考字段需要4个字节。 int:4个字节,
长8
短2(在Dalvik上为4),
布尔1字节(Sun),4字节Dalvik;

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

根据joda-time的说法,它们提供了处理日期的最佳方法:

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

创建Joda-Time是为了从根本上改变Java中的日期和时间处理。 JDK类Date和Calendar的设计很糟糕,有很多错误,并且效果奇特。 这是我们开发和使用Joda-Time的一些原因:

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

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

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

但是,如果您对此不感兴趣,请查看该问题以获取操作系统级别的系统信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM