2013-05-09 49 views
5

我編寫了一個小型java程序,它使用簡單的JDBC調用從DB2數據庫加載數據。我正在使用select查詢來獲取數據併爲此使用java語句。我已經正確關閉了語句和連接對象。我正在使用64位JVM進行編譯和運行程序。爲什麼我的JDBC調用消耗內存的數據量是實際大小的4倍

查詢返回5200萬條記錄,每行有24列,這需要我花4分鐘才能在Unix(具有多處理器環境)中加載完整數據。我使用HashMap作爲數據結構來加載數據:Map<String, Map<String, GridTradeStatus>>。 Bean GridTradeStatus是一個簡單的getter/setter bean,其中包含24個屬性。

該程序所需的內存驚人地高。 Java堆大小上升到5.8 - 6GB來加載完整的數據,而實際使用的堆大小保持在4.7 - 4.9GB之間。我知道我們不應該將這麼多的數據加載到內存中,但是我的業務需求只能以這種方式進行。

問題是,當我將我的表的整個數據放在一個平面文件中時,它大致相當於〜1.2GB。我想知道爲什麼我的Java程序消耗的內存是其實際大小的4倍多。

+0

java中的字符串使用UTF-16,每個字符表示2個字節。所以如果你的txt文件是一個普通的8位/字符編碼,那麼會導致雙倍的內存使用率。此外,如果您使用子字符串方法,請記住,只要子字符串對象處於活動狀態,就會釋放原始字符串newer。 – MTilsted 2013-05-09 12:35:51

+0

感謝您的評論。是否有可能指示JVM使用UTF-8編碼? – 2013-05-10 05:13:36

+0

不是直接。 java.lang.String將始終使用UTF-16。但我相信,谷歌搜索可以給你一個java字符串類,它使用utf-8或其他8位編碼。 – MTilsted 2013-05-10 11:26:25

回答

0

這裏沒有什麼奇怪的東西(對我來說至少)。

a)與大多數常見文本格式相比,java中的字符串消耗的空間增加了一倍(因爲字符串在堆中始終表示爲UTF-16)。另外,作爲一個對象的String有相當的開銷(String對象本身,它包含的char []的引用,hashCode等)。對於小字符串,String對象與其所包含的數據一樣容易獲得儘可能多的內存。

b)將東西放入HashMap。 HashMap不是完全有效的內存。首先,它使用75%的默認加載因子,這意味着具有多個條目的地圖也有一個大型的數組。然後,映射中的每個條目都是一個對象本身,它至少需要兩個引用(鍵和值)以及對象開銷。

總之你幾乎不得不期望的內存需求增加不少。如果您的平均數據字符串相對較短,則係數4是合理的。

0

如果您認爲您無法承受平面文件中的數據大小與在HashMap中加載字符串所需的內存之間的比例1:4,則應考慮不使用Java,而應使用較低級別的語言,如C++或甚至C.

當然也有可能的優化:

  • 使用byte[]代替String(一半大小)
  • 不使用缺省HashMap參數(初始大小/負載因子),但調整他們會見你實際需求。

以下主要是經驗意見爲準。我通常使用4種語言級別:

  • 高級腳本語言(Python,Ruby或甚至bash ...)性能 不是一個要求和開發速度是
  • 中級語言(Java,不太頻繁的高級C++)當性能問題時,但當我也想簡單的開發和健壯性(強打字,......)
  • 低級語言(低電平C++或C)有什麼性能要求比較高,當我接受花更多的時間在編寫和測試各個模塊
  • 彙編語言用於小部件在性能關鍵,已被證明是通過分析。

恕我直言,你可以調整Java代碼來高度減少內存佔用,但風險由失去優秀的字符串和集合的支持失去了Java的興趣的很大一部分。在C++中編寫一小部分應用程序並使用JNI將所有代碼連接起來可能會很簡單,也許更有效。

相關問題