将内存消耗减少20倍
這將是另一個故事,與我們分享有關內存相關問題的最新經驗。 該案例是從最近的客戶支持案例中提取的,在該案例中,我們遇到了一個行為異常嚴重的應用程序,該應用程序因生產中的OutOfMemoryError消息而死亡。 在連接了Plumbr的情況下運行應用程序之后,我們確定這次不會遇到內存泄漏。 但是仍然有一些嚴重的錯誤。
癥狀是通過監視某些數據結構的開銷的一項實驗功能發現的。 它給了我們一個信號,指出了源代碼中的一個特定位置。 為了保護客戶的隱私,我們使用合成樣本重新制作了案件,同時在技術上使其與原始問題相同。 隨時下載源代碼 。
我們發現自己盯著從外部源加載的一組對象。 與外部系統的通信是通過XML接口實現的。 這本身還不錯。 但是,集成實現細節分散在整個系統中(將收到的文檔轉換為XMLBean實例,然后在整個系統中使用)的事實可能并不是最明智的選擇。
本質上,我們正在處理延遲加載的緩存解決方案。 緩存的對象是人物:
不太可能消耗內存。 但是,當我們打開一些更多的細節時,情況看起來會變得有些酸。 也就是說,該數據的實現類似于上面的簡單類聲明。 相反,該實現使用了模型生成的數據結構。 使用的模型類似于以下簡化的XSD代碼段:
<xs:schema targetNamespace="http://plumbr.eu" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="id" type="xs:string"/> <xs:element name="dateOfBirth" type="xs:dateTime"/> <xs:element name="forename" type="xs:string"/> <xs:element name="surname" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>開發人員使用XMLBeans生成了在后臺使用的模型。 現在讓我們添加一個事實,即緩存應該容納多達130萬個Persons實例,并且我們為失敗奠定了堅實的基礎。
運行捆綁的測試用例表明,基于XMLBean的解決方案的130萬個實例將消耗大約1.5 GB的堆。 我們認為我們可以做得更好。
第一個解決方案是顯而易見的。 集成細節不應跨越系統邊界。 因此,我們將緩存解決方案更改為簡單的java.util.HashMap <Long,Person>解決方案。 以ID為鍵,以Person對象為值。 立刻我們發現內存消耗減少到214MB 。 但是我們還不滿意。
由于Map中的鍵本質上是數字,因此我們有所有理由使用Trove Collections來進一步減少開銷。 實現中的快速更改,我們已用TLongObjectHashMap <Person>替換了HashMap 。 堆消耗降至143MB 。
我們當然可以在這里停下來,但是出于工程方面的好奇心,我們不允許這樣做。 我們不禁注意到所使用的數據包含冗余信息。 出生日期實際上是在ID中編碼的,因此我們可以輕松地從給定的ID計算生日,而不是將其復制到其他字段中。
因此,我們更改了Person對象的布局,現在它僅包含以下字段:
// Imports and methods removed to improve readability public class Person { private long id; private String forename; private String surname; }重新運行測試證實了我們的期望。 堆消耗降至93MB 。 但是我們仍然不滿意。
該應用程序在具有舊JDK6版本的64位計算機上運行。 默認情況下不壓縮普通對象指針。 切換到-XX:+ UseCompressedOops給了我們額外的勝利-現在我們的內存已減少到73MB 。
我們可以走得更遠,開始實習字符串或基于鍵構建b樹,但這已經開始影響代碼的可讀性,因此我們決定在這里停止。 21.5倍的堆減少應該已經足夠好了。
得到教訓?
- 不要讓集成細節跨越系統邊界
- 冗余數據將耗資巨大。 盡可能刪除冗余。
- 原始人是您的朋友。 了解您的工具并學習Trove(如果您還沒有的話)
- 注意JVM提供的優化技術
如果您對進行的實驗感到好奇,請隨時從此處下載使用的代碼 。 描述了用于測量的實用程序,并在此博客文章中提供了該實用程序。
翻譯自: https://www.javacodegeeks.com/2013/06/reducing-memory-consumption-by-20x.html
總結
以上是生活随笔為你收集整理的将内存消耗减少20倍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Data Solr教程:排
- 下一篇: (linux的set)