9 use Storable qw(dclone);
12 'db=s' => \(my $opt_db = '../memnodes.db'),
13 'debug!' => \my $opt_debug,
16 #warn "Reading from $opt_db\n";
19 file => '../memnodes.db',
26 my $j = JSON::XS->new;
28 # Documentation browser under "/perldoc"
33 $self->render('index');
36 get '/jit_tree/:id/:depth' => sub {
38 my $logarea = $self->param('logarea');
40 my $id = $self->stash('id');
41 my $depth = $self->stash('depth');
42 my $node_tree = _fetch_node_tree($id, $depth);
43 my $jit_tree = _transform_node_tree($node_tree, sub {
45 my $children = delete $node->{children}; # XXX edits the src tree
46 my $area = $node->{self_size}+$node->{kids_size};
47 $node->{'$area'} = ($logarea) ? log($area) : $area; # XXX move to jit js
50 name => $node->{title} || $node->{name},
53 $jit_node->{children} = $children if $children;
58 use Data::Dump qw(pp);
59 local $jit_tree->{children};
60 pp(dclone($jit_tree)); # dclone to avoid stringification
62 $self->render_json($jit_tree);
65 sub _fetch_node_tree {
66 my ($id, $depth) = @_;
67 my $node = MemView->selectrow_hashref("select * from node where id = ?", undef, $id)
68 or die "Node '$id' not found";
69 $node->{$_} += 0 for (qw(child_count kids_node_count kids_size self_size));
70 $node->{leaves} = $j->decode(delete $node->{leaves_json});
71 $node->{attr} = $j->decode(delete $node->{attr_json});
72 $node->{name} .= "->" if $node->{type} == 2 && $node->{name};
74 if ($node->{child_ids}) {
75 my @child_ids = split /,/, $node->{child_ids};
77 if (@child_ids == 1 && $node->{type} == 2) {
78 my $child = _fetch_node_tree($child_ids[0], $depth); # same depth
79 # merge node into child
80 # XXX id, depth, parent_id
81 warn "Merged $node->{name} #$node->{id} with only child $child->{name} #$child->{id}\n"
83 $child->{name} = "$node->{name} $child->{name}";
84 $child->{$_} += $node->{$_} for (qw(self_size));
85 $child->{$_} = $node->{$_} for (qw(parent_id));
87 $child->{title} = join " ", grep { defined && length } $child->{title}, $node->{title};
88 #warn "Titled $child->{title}" if $child->{title};
90 for my $attr_type (keys %{ $node->{attr} }) {
91 my $src = $node->{attr}{$attr_type};
92 if (ref $src eq 'HASH') { # eg NPattr_NAME: {attr}{1}{$name} = $value
93 my $dst = $child->{attr}{$attr_type} ||= {};
94 for my $k (keys %$src) {
95 warn "Node $child->{id} attr $attr_type:$k=$dst->{$k} overwritten by $src->{$k}\n"
96 if defined $dst->{$k};
97 $dst->{$k} = $src->{$k};
100 elsif (ref $src eq 'ARRAY') { # eg NPattr_PADNAME: {attr}{2}[$val] = $name
101 my $dst = $child->{attr}{$attr_type} ||= [];
103 while (--$idx >= 0) {
104 warn "Node $child->{id} attr $attr_type:$idx=$dst->[$idx] overwritten by $src->[$idx]\n"
105 if defined $dst->[$idx];
106 $dst->[$idx] = $src->[$idx];
109 else { # assume scalar
110 warn "Node $child->{id} attr $attr_type=$child->{attr}{$attr_type} overwritten by $src\n"
111 if exists $child->{attr}{$attr_type};
112 $child->{attr}{$attr_type} = $src;
116 $child->{leaves}{$_} += $node->{leaves}{$_}
117 for keys %{ $node->{leaves} };
119 $child->{_ids_merged} .= ",$node->{id}";
120 my @child_ids = split /,/, $node->{child_ids};
121 $child->{child_count} = @child_ids;
126 $children = [ map { _fetch_node_tree($_, $depth-1) } @child_ids ];
127 $node->{children} = $children;
128 $node->{child_count} = @$children;
134 sub _transform_node_tree { # recurse depth first
135 my ($node, $transform) = @_;
136 if (my $children = $node->{children}) {
137 $_ = _transform_node_tree($_, $transform) for @$children;
139 return $transform->($node);
148 Welcome to the Mojolicious real-time web framework!
150 @@ layouts/default.html.ep
153 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
154 <title>Perl Memory Treemap</title>
157 <link type="text/css" href="css/base.css" rel="stylesheet" />
158 <link type="text/css" href="css/Treemap.css" rel="stylesheet" />
160 <!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
162 <!-- JIT Library File -->
163 <script language="javascript" type="text/javascript" src="jit.js"></script>
164 <script language="javascript" type="text/javascript" src="jquery-1.8.1-min.js"></script>
166 <!-- Example File -->
167 <script language="javascript" type="text/javascript" src="sprintf.js"></script>
168 <script language="javascript" type="text/javascript" src="tm.js"></script>
171 <body onload="init();">
174 <div id="left-container">
180 Click on a node to zoom in.<br /><br />
183 <a id="back" href="#" class="theme button white">Go to Parent</a>
187 <label for="logarea"> Logarithmic scale
188 <input type=checkbox id="logarea" name="logarea">
193 <div id="center-container">
194 <div id="infovis"></div>
197 <div id="right-container">
199 <div id="inner-details"></div>