Webエンジニア susumuis の技術ブログ

このブログの内容は個人の見解であり、所属する組織の公式見解ではありません

64bit環境でなんかheapを多く消費するなあと思ったら

かいつまんで話すと、100KBくらいのXMLデータをモデル化したデータ*1Javaのheap上で10MBになった!なぜか!という話です。

DOMのような構造データは要するにこんなデータ構造を持っていれば良いです。

class Node {
    Map<String, String> attribute;
    QName qName;
}

class QName {
    URI uri;
    String tagName;
}

URIは適切にキャッシュを共有する必要があります*2が、そこさえ気をつければ、必要な実データは要するに元のXMLテキストデータとあまり変わらない。改行コードとインデントがなくなるのでむしろ軽くなるはずです!

となると、オーバーヘッドはオブジェクトの管理データだと予想しました。
https://www.ibm.com/developerworks/jp/java/library/j-codetoheap/
を読んだ程度の理解ですが、64bitモード下でのJavaのオブジェクトは結構大きなデータなのですね。100byte以上とはでかいですね。そこで、HotspotVMには圧縮OOPというものが搭載されていて、
http://docs.oracle.com/javase/jp/7/technotes/guides/vm/performance-enhancements-7.html
>> 6u23 リリースより前の JDK 6 でこの機能を有効にするには、java コマンドで -XX:+UseCompressedOops フラグを使用します。
とのことです。つまり、

  • 32bit VMで十分なメモリの量だったら、32bit VMを使ったほうが有利(〜2GBくらいか?)
  • 64bitが必要で、Java 6u13以前だったら、VMのバージョンアップを検討すべき
  • 64bitが必要で、Java 6u14以上6u22以前だったら、-XX:+UseCompressedOops フラグを使用か、VMのバージョンアップを検討すべき

というか、GCも進化してるし、Java VMは最新を使おう!

*1:正確に言えば、MayaaのSpecificationCacheのことですが直接関係ないのでここでは深く突っ込ません

*2:そうしないと1タグ毎に "http://www.w3.org/1999/xhtml" とかを保持することになる