簡體   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