clojureを分解する(4)


以前jdkについてきた、面白そうなツールを上げたけど、その中で唯一使っていなかった
ものがあったので、man を頼りに試してみた。

そのコマンドとは、jhat。manによると

Name
       jhat - Java Heap Analysis Tool

JVMのメモリーエリアったら、Heap だから、これはひょっとして、coredumpの解析ツール
相当になるのかしらん。

jhatを使うには、あらかじめ、jmapを使って、dumpファイルを作成しておく。
clojure のREPLに入った所で、別窓からjps して、対象JVMのプロセス番号(今回は、3120)を
得ておく。

sakae@debian:~$ jmap -dump:format=b,file=mar30 3120
Dumping heap to /home/sakae/mar30 ...
Heap dump file created
sakae@debian:~$ ls -l mar30
-rw------- 1 sakae sakae 4315022 Mar 30 15:28 mar30

4Mのcoreが得られたけど、比較的早く終了した。
続いて、jhatを起動する。

sakae@debian:~$ jhat mar30
Reading from mar30...
Dump file created Mon Mar 30 15:28:55 JST 2009
Snapshot read, resolving...
Resolving 39249 objects...
Chasing references, expect 7 dots.......
Eliminating duplicate references.......
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

readyになるまで、随分と待たされました。
後は、クリック猿よろしく、Webから見ていけば良い。

sakae@debian:~$ w3m http://localhost:7000/

あうぅ、w3mでは、生htmlが表示されてしまったわい。何故だろう?
そうか、text/html を送って来ないんだな。だったら、htmlのソースとhtmlの解析結果を
切り替えてやればいいんだ。えーと、v で、トグルするんだったわい。
Sunよ。ヘッダー情報ぐらいちゃんと送出しなはれ。俺が苦労するじゃん。

---------------------------------------------------------------------------
                       All Classes (excluding platform)

Package 

class [Lclojure.asm.Item; [0x902fc1d8]
class [Lclojure.asm.Type; [0x900e4498]
 :
Package clojure

class clojure.core$_DOT__DOT___3254 [0x9015ac00]
class clojure.core$_EQ__EQ___3025 [0x90139bf8]
 :
Package clojure.lang

class clojure.lang.AFn [0x90006dd0]
class clojure.lang.AFunction [0x90057820]
 :
Package clojure

class clojure.main [0x8fff51b0]
class clojure.main$_main__5222 [0x902dbe10]
 :
Other Queries

  * All classes including platform
  * Show all members of the rootset
  * Show instance counts for all classes (including platform)
  * Show instance counts for all classes (excluding platform)
  * Show heap histogram
  * Show finalizer summary
  * Execute Object Query Language (OQL) query
------------------------------------------------------------------------------

結構な数のクラスが鎮座してました。
次は、Show instance counts for all classes (excluding platform)をつついてみます。

-------------------------------------------------------------------------------
             Instance Counts for All Classes (excluding platform)

4046 instances of class clojure.lang.PersistentHashMap$LeafNode
2679 instances of class clojure.lang.Symbol
1688 instances of class [Lclojure.lang.PersistentHashMap$INode;
 :
0 instances of class [Lclojure.lang.Sequential;
0 instances of class [Lclojure.lang.Streamable;
--------------------------------------------------------------------------------

LeafNodeって、consセルの事? 後で、ソースを当たってみよう。
クラスによっては、インスタンスを持たないものも居るのね。
それじゃ、先日見た、set$union を覗いてみます。

---------------------------------------------------------------------------------
                               Class 0x902c4cc0

class clojure.set$union__5229

Superclass:

class clojure.lang.AFunction

Loader Details

ClassLoader:

sun.misc.Launcher$AppClassLoader@0x8c4e6990 (63 bytes)

Signers:



Protection Domain:

java.security.ProtectionDomain@0x8c4e69d8 (26 bytes)

Subclasses:

Instance Data Members:

Static Data Members:

const__1 (L) : clojure.lang.Var@0x8c510a30 (32 bytes)
const__0 (L) : clojure.lang.Var@0x8c527590 (32 bytes)

Instances
Exclude subclasses
Include subclasses

References summary by Type

References summary by type

References to this object:

clojure.set$union__5229@0x8c5760c0 (12 bytes) : ??
[Ljava.lang.Object;@0x8c55ec98 (5128 bytes) : Element 738 of
[Ljava.lang.Object;@0x8c55ec98

Other Queries

Reference Chains from Rootset

  * Exclude weak refs
  * Include weak refs

References summary by Type

Objects reachable from here
---------------------------------------------------------------------------------

クリックする所がたくさんあって楽しいわい。しかも、地雷付きときたら最高でっせ。
なんせ、へたな所をポイントしたら、さっぱりレスポンスが帰ってきませんから。
私はゲームはしませんが、これって、世に言うマインスイーパーでっしゃろか。
遊び心満載のツールでしたよ。Sun最高!!!
遊んでいたら、大分紙面を消費してしまったわい。
最後に、set$union とは、何するものぞを調べてみました。って、集合演算ですね。

user=> (union #{:a :b :c} #{:b :c :d})
java.lang.Exception: Unable to resolve symbol: union in this context (NO_SOURCE_FILE:1)
user=> (use 'clojure.set)
nil
user=> (union #{:a :b :c} #{:b :c :d})
#{:d :a :b :c}

集合演算なんてめったに使わないので、使うぜ宣言しないと有効にならないのね。
JVM上では、ロードされてるんだけどなぁ。変な仕様だ事。