かいつまんで話すと、100KBくらいのXMLデータをモデル化したデータ*1がJavaの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" とかを保持することになる