简体   繁体   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

I was wondering about the memory consumption by 我想知道内存消耗

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

I need to create a bunch of objects which have some Dates, today they are timestamps as longs but this does not so nice and creates CPU load on the other side because I need the dates. 我需要创建一堆具有一些日期的对象,今天它们是很长的时间戳,但这不太好,并且由于我需要日期而在另一侧创建了CPU负载。

So my question is: Is there any statistic available? 所以我的问题是:是否有可用的统计数据? How to measure such things probably? 大概如何衡量这种事情?

I wouldn't worry about it, you would need millions of Objects for this to really make a difference on a server. 我不用担心,您需要数百万个对象才能真正在服务器上发挥作用。

But if you really want to know, you can look at the implementations to see the fields of each object, and the fields of each parent object etc and the fields of each referenced object). 但是,如果您真的想知道,则可以查看实现以查看每个对象的字段,每个父对象的字段等以及每个引用的对象的字段。 You can add up the number bytes used by each field + the size of an object reference (4 or 8 bytes depending on JVM) plus padding described in the Java spec. 您可以累加每个字段使用的字节数+对象引用的大小(4或8个字节,取决于JVM)加上Java规范中描述的填充。

Or you can use 3rd party libraries such as java.sizeOf which will do this for you. 或者,您可以使用第3方库(例如java.sizeOf)为您完成此操作。

But taking a quick look at the code of the classes you asked about, here are the fields: 但是,快速浏览一下您要查询的类的代码,以下是这些字段:

Date: 日期:

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 + reference to other class which has its own fields etc. However, after lots of code reading, cdate is almost alwasy null so we only have to count the size of the object reference (to null) which I think won't bloat up the size of the object beyond the padding of 24 bytes when using a 32-bit or if on 64 bit, using compressed Ops which tries to use 4 byte references instead of 8 when possible. long +对具有其自己的字段等的其他类的引用。但是,经过大量的代码阅读, cdate几乎都是null因此我们只需要计算对象引用的大小(为null),我认为这不会膨胀使用32位或64位时,对象的大小超出24字节填充的范围,请使用压缩的Ops,它会尝试使用4字节引用而不是8字节引用。 (I think this is default on Java 8) so we can ignore it. (我认为这是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;

So int+short+short takes the same size as long but you have to account for the memory of each LocalDate reference you keep around. 因此, int+short+short的大小与long相同,但是您必须考虑保留的每个LocalDate引用的内存。

Datetime: 约会时间:

 private long iMillis;


 private Chronology iChronology;

Which is also long + object ref to other object that takes up memory. 这也是long +对其他占用内存的对象的引用。

Using SizeOf 使用SizeOf

When I created an instance of each object and used java.sizeOf on them on my 64bit Java 8 JVM I got the following memory sizes (in bytes): 当我创建每个对象的实例并在64位Java 8 JVM上对它们使用java.sizeOf时,我得到了以下内存大小(以字节为单位):

javaDate = 24    
localDate = 24

dateTime = 16928

As you can see jodatime takes up a lot of memory with all of its supporting classes. 如您所见,jodatime的所有支持类都占用大量内存。 Much of it will be reused when you have other instances though. 但是,当您拥有其他实例时,其中的大部分将被重用。

Therefore, I would go with keep using your long s if they aren't wrapped in a class. 因此,如果您的long不在类中,我将继续使用它们。 But if you are wrapping your long in a class, or even using Long , LocalDate seems best since it's the same amount of memory plus all the supporting classes for converting/ timezones etc. I would not use Date since that class is mutable and should be considered deprecated. 但是,如果您将long封装在一个类中,或者甚至使用Long ,则LocalDate似乎是最好的,因为它的内存量相同,加上所有支持的类用于转换/时区等。我不会使用Date因为该类是可变的,应该被认为已弃用。

  1. Most efficient; 最有效 storing in a long value: 8 bytes (further it is immutable when passed as param) 以长值存储:8个字节(此外,作为参数传递时,它是不可变的)

  2. Java.util.Date Java.util.Date
    VM 64 bit: 12 for the object +8 for long value + 4 for ref to BaseCal.Date = 24 bytes VM 64位:对象的12个+长值的8个+引用BaseCal.Date的4个= 24字节
    Sun VM 32 bit: 8 + 8 + 4 = 20 + 4 padding = 24 bytes Sun VM 32位:8 + 8 + 4 = 20 + 4填充= 24​​字节
    (Not recomendable since has not any advantage, is mutable, needs more memory) (不可推荐,因为没有任何优势,可变,需要更多内存)

    There are implementation (IBM Embedded Java where Date has only one field) (That would be 16 bytes minimal) 有实现(IBM嵌入式Java,其中Date仅具有一个字段)(这将是最少16个字节)

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

  4. joda DateTime 乔达日期时间
    VM 64 bit: 12 + 8 + 4 for the reference to Chronology: = 24 bytes VM 64位:12 + 8 + 4,用于编年表:= 24字节
    VM 32 bit: 8 + 8 + 4 for the reference to Chronology + 4 padding = 24 bytes VM 32位:8 + 8 + 4,用于编年表参考+ 4个填充= 24​​字节

How to measure such things probably? 大概如何衡量这种事情? On Sun VM you can use MAT which uses a special featuire of the Sun VM. 在Sun VM上,您可以使用MAT,它使用Sun VM的特殊功能。 (see the answer of Szymon Krawczyk) On other VM its is difficult to measure and any code which I have seen (MemoryTestBench based on heap size, gc calls etc.) failed in some situations, giving negative memory consumption. (请参阅Szymon Krawczyk的答案)在其他VM上,它很难衡量,而且我所见的任何代码(基于堆大小的MemoryTestBench,gc调用等)在某些情况下均会失败,从而导致内存消耗为负。

The most correct way is to count it yourself: 最正确的方法是自己计算:

Depening on the VM an empty objects needs 8 byte Sun VM 32, or 12 Sun VM64 + Dalvik + the object size always is padded to next multiple of 8 bytes. 在VM上分配空对象需要8字节的Sun VM 32或12 Sun VM64 + Dalvik +对象大小始终填充为8字节的下一个倍数。

Fields 领域
A reference field needs 4 bytes. 参考字段需要4个字节。 int: 4 bytes, int:4个字节,
long 8, 长8
short 2 (or 4 on Dalvik), 短2(在Dalvik上为4),
boolean 1 byte (Sun) , 4 bytes Dalvik; 布尔1字节(Sun),4字节Dalvik;

An array is an object + an int field (array.length) = 16 bytes, except on Dalvik where for strange reasons it needs 20 bytes ( + 4 padding if no elemens) = 24 数组是一个对象+一个int字段(array.length)= 16字节,Dalvik除外,在Dalvik上它出于奇怪的原因需要20字节(如果没有元素则需要+ 4填充)= 24

According to joda-time, they offer the best way to work with dates: 根据joda-time的说法,它们提供了处理日期的最佳方法:

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

Joda-Time has been created to radically change date and time handling in Java. 创建Joda-Time是为了从根本上改变Java中的日期和时间处理。 The JDK classes Date and Calendar are very badly designed, have had numerous bugs and have odd performance effects. JDK类Date和Calendar的设计很糟糕,有很多错误,并且效果奇特。 Here are some of our reasons for developing and using Joda-Time: 这是我们开发和使用Joda-Time的一些原因:

  • Easy to Use. 易于使用。 Calendar makes accessing 'normal' dates difficult, due to the lack of simple methods. 由于缺少简单的方法,日历使访问“正常”日期变得困难。 Joda-Time has straightforward field accessors such as getYear() or getDayOfWeek(). Joda-Time具有直接的字段访问器,例如getYear()或getDayOfWeek()。
  • Easy to Extend. 易于扩展。 The JDK supports multiple calendar systems via subclasses of Calendar. JDK通过Calendar的子类支持多种日历系统。 This is clunky, and in practice it is very difficult to write another calendar system. 这很笨拙,在实践中很难编写另一个日历系统。 Joda-Time supports multiple calendar systems via a pluggable system based on the Chronology class. Joda-Time通过基于Chronology类的可插拔系统支持多个日历系统。
  • Comprehensive Feature Set. 全面的功能集。 The library is intended to provide all the functionality that is required for date-time calculations. 该库旨在提供日期时间计算所需的所有功能。 It already provides out-of-the-box features, such as support for oddball date formats, which are difficult to replicate with the JDK. 它已经提供了开箱即用的功能,例如对奇数日期格式的支持,这些功能很难用JDK复制。
  • Up-to-date Time Zone calculations. 最新的时区计算。 The time zone implementation is based on the public tz database, which is updated several times a year. 时区实现基于公共tz数据库,该数据库每年更新几次。 New Joda-Time releases incorporate all changes made to this database. 新的Joda-Time版本包含对该数据库所做的所有更改。 Should the changes be needed earlier, manually updating the zone data is easy. 如果较早需要更改,则手动更新区域数据很容易。
  • Calendar support. 日历支持。 The library currently provides 8 calendar systems. 该图书馆目前提供8种日历系统。 More will be added in the future. 将来会添加更多。
  • Easy interoperability. 易于互操作。 The library internally uses a millisecond instant which is identical to the JDK and similar to other common time representations. 该库在内部使用毫秒级的瞬间,该瞬间与JDK相同,并且与其他常见时间表示类似。 This makes interoperability easy, and Joda-Time comes with out-of-the-box JDK interoperability. 这使互操作性变得容易,并且Joda-Time具有开箱即用的JDK互操作性。
  • Better Performance Characteristics. 更好的性能特征。 Calendar has strange performance characteristics as it recalculates fields at unexpected moments. 由于Calendar在意外的时刻重新计算字段,因此它具有奇怪的性能特征。 Joda-Time does only the minimal calculation for the field that is being accessed. Joda-Time仅对要访问的字段进行最少的计算。
  • Good Test Coverage. 良好的测试覆盖率。 Joda-Time has a comprehensive set of developer tests, providing assurance of the library's quality. Joda-Time有一套全面的开发人员测试,可确保图书馆的质量。
  • Complete Documentation. 完整的文档。 There is a full User Guide which provides an overview and covers common usage scenarios. 有完整的用户指南,提供了概述并涵盖了常见的使用场景。 The javadoc is extremely detailed and covers the rest of the API. Javadoc非常详细,涵盖了API的其余部分。
  • Maturity. 到期。 The library has been under active development since 2002. Although it continues to be improved with the addition of new features and bug-fixes, it is a mature and reliable code base. 自2002年以来,该库一直在积极开发中。尽管通过添加新功能和错误修复对其进行了不断改进,但它是一个成熟而可靠的代码库。 A number of related projects are now available. 现在有许多相关项目。
  • Open Source. 开源。 Joda-Time is licenced under the business friendly Apache License Version 2.0. Joda-Time已获得商业友好型Apache许可证版本2.0的许可。

And by personal experience, I agree with them. 根据个人经验,我同意他们的观点。 But, you can analyse it better using jvisualvm (jdk/bin) profiling tool, while running your application. 但是,您可以在运行应用程序时使用jvisualvm (jdk / bin)分析工具更好地对其进行分析。

I can comment but in terms of memory usage u can take a memory dump (heap dump) of running app by doing that: jmap -dump:format=b,file=cheap.bin <pid> 我可以发表评论,但是就内存使用而言,您可以通过执行以下操作来获取正在运行的应用程序的内存转储(堆转储): jmap -dump:format=b,file=cheap.bin <pid>
Then install MAT of course if you are using ECLIPSE open that file in eclipse and compare objects sizes. 如果使用ECLIPSE,则当然要安装MAT ,然后在eclipse中打开该文件并比较对象大小。 I used that to find out memory leaks in my web app with servlets and Tomcat server It is really useful 我用它来找出带有servlet和Tomcat服务器的Web应用程序中的内存泄漏,这真的很有用

But if you are not interested in that take look on that question get OS-level system information 但是,如果您对此不感兴趣,请查看该问题以获取操作系统级别的系统信息

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

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