我想知道
的内存消耗情况java.util.Date
java.time.LocalDate
org.joda.time.DateTime
我需要创建一堆具有一些Dates的对象,今天它们的时间戳是长的但是这不太好并且在另一侧创建CPU负载因为我需要日期。
所以我的问题是:有没有统计数据? 如何测量这些东西呢?
答案 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+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 :(得分:1)
效率最高;以长值存储:8个字节(当它作为参数传递时,它是不可变的)
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字节)
LOCALDATE
VM 64位:12 + 4 + 2 + 2 = 20 + 4填充= 24字节
VM 32位:8 + 4 + 2 + 2 = 16字节;
在android Dalvik:12 + 4 + 4 + 4 = 24字节
joda DateTime
VM 64位:12 + 8 + 4用于参考年表:= 24个字节
VM 32位:8 + 8 + 4用于参考年表+ 4填充= 24字节
如何衡量这些事情呢? 在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的一些原因:
根据个人经验,我同意他们的看法。但是,您可以在运行应用程序时使用 jvisualvm (jdk / bin)分析工具更好地分析它。
答案 3 :(得分:0)
我可以发表评论,但就内存使用而言,你可以通过这样做获取运行应用程序的内存转储(堆转储):
jmap -dump:format=b,file=cheap.bin <pid>
然后安装MAT当然如果您正在使用ECLIPSE在eclipse中打开该文件并比较对象大小。
我用它来查找我的web应用程序中使用servlet和Tomcat服务器的内存泄漏
这真的很有用
但是如果你对这个问题不感兴趣,可以看一下get OS-level system information