smarten up the tooltip
[p5sagit/Devel-Size.git] / memnodes.pl
CommitLineData
2c631ee0 1#!/bin/env perl
2
3use strict;
4use warnings;
5
b2fc39a5 6use DBI;
7use DBD::SQLite;
f60f09e5 8use JSON::XS;
b2fc39a5 9
fc6614ee 10use Getopt::Long;
11
12GetOptions(
13 'json!' => \my $opt_json,
b2fc39a5 14 'db=s' => \my $opt_db,
fc6614ee 15) or exit 1;
94fab3d1 16
f60f09e5 17my $j = JSON::XS->new->ascii->pretty(0);
18
b2fc39a5 19my $dbh = DBI->connect("dbi:SQLite:dbname=$opt_db","","", {
20 RaiseError => 1, PrintError => 0, AutoCommit => 0
21});
22$dbh->do("PRAGMA synchronous = OFF");
23$dbh->do("DROP TABLE IF EXISTS node");
24$dbh->do(q{
25 CREATE TABLE node (
26 id integer primary key,
27 name text,
28 depth integer,
5a78486c 29 parent_id integer,
b2fc39a5 30
31 self_size integer,
32 kids_size integer,
33 kids_node_count integer,
f60f09e5 34 child_ids text,
e78b28ca 35 attr_json text,
36 leaves_json text
b2fc39a5 37 )
38});
39my $node_ins_sth = $dbh->prepare(q{
e78b28ca 40 INSERT INTO node VALUES (?,?,?,?, ?,?,?,?,?,?)
b2fc39a5 41});
42
2c631ee0 43my @stack;
44my %seqn2node;
45
94fab3d1 46sub enter_node {
47 my $x = shift;
48 if ($opt_json) {
49 print " " x $x->{depth};
b2fc39a5 50 print qq({ "id": "$x->{id}", "name": "$x->{name}", "depth":$x->{depth}, "children":[ \n);
94fab3d1 51 }
52 return;
53}
54
55sub leave_node {
56 my $x = shift;
b2fc39a5 57 delete $seqn2node{$x->{id}};
94fab3d1 58 my $self_size = 0; $self_size += $_ for values %{$x->{leaves}};
59 $x->{self_size} = $self_size;
2c631ee0 60 if (my $parent = $stack[-1]) {
61 # link to parent
5a78486c 62 $x->{parent_id} = $parent->{id};
2c631ee0 63 # accumulate into parent
64 $parent->{kids_node_count} += 1 + ($x->{kids_node_count}||0);
94fab3d1 65 $parent->{kids_size} += $self_size + $x->{kids_size};
5a78486c 66 push @{$parent->{child_id}}, $x->{id};
2c631ee0 67 }
68 # output
69 # ...
94fab3d1 70 if ($opt_json) {
71 print " " x $x->{depth};
72 my $size = $self_size + $x->{kids_size};
73 print qq(], "data":{ "\$area": $size } },\n);
74 }
b2fc39a5 75 if ($dbh) {
f60f09e5 76 my $attr_json = $j->encode($x->{attr});
e78b28ca 77 my $leaves_json = $j->encode($x->{leaves});
b2fc39a5 78 $node_ins_sth->execute(
5a78486c 79 $x->{id}, $x->{name}, $x->{depth}, $x->{parent_id},
b2fc39a5 80 $x->{self_size}, $x->{kids_size}, $x->{kids_node_count},
f60f09e5 81 $x->{child_id} ? join(",", @{$x->{child_id}}) : undef,
e78b28ca 82 $attr_json, $leaves_json,
b2fc39a5 83 );
84 # XXX attribs
85 }
94fab3d1 86 return;
2c631ee0 87}
88
94fab3d1 89print "memnodes = [" if $opt_json;
90
2c631ee0 91while (<>) {
92 chomp;
b2fc39a5 93 my ($type, $id, $val, $name, $extra) = split / /, $_, 5;
2c631ee0 94 if ($type eq "N") { # Node ($val is depth)
95 while ($val < @stack) {
94fab3d1 96 leave_node(my $x = pop @stack);
b2fc39a5 97 warn "N $id d$val ends $x->{id} d$x->{depth}: size $x->{self_size}+$x->{kids_size}\n";
2c631ee0 98 }
99 die 1 if $stack[$val];
b2fc39a5 100 my $node = $stack[$val] = { id => $id, name => $name, extra => $extra, attr => [], leaves => {}, depth => $val, self_size=>0, kids_size=>0 };
94fab3d1 101 enter_node($node);
b2fc39a5 102 $seqn2node{$id} = $node;
2c631ee0 103 }
104 elsif ($type eq "L") { # Leaf name and memory size
b2fc39a5 105 my $node = $seqn2node{$id} || die;
2c631ee0 106 $node->{leaves}{$name} += $val;
107 }
108 elsif ($type eq "A") { # Attribute name and value
b2fc39a5 109 my $node = $seqn2node{$id} || die;
2c631ee0 110 push @{ $node->{attr} }, $name, $val; # pairs
111 }
112 else {
113 warn "Invalid type '$type' on line $. ($_)";
114 }
b2fc39a5 115 $dbh->commit if $dbh and $id % 10_000 == 0;
2c631ee0 116}
117
118my $x;
119while (@stack > 1) {
94fab3d1 120 leave_node($x = pop @stack) while @stack;
b2fc39a5 121 warn "EOF ends $x->{id} d$x->{depth}: size $x->{self_size}+$x->{kids_size}\n";
2c631ee0 122}
94fab3d1 123print " ];\n" if $opt_json;
124
b2fc39a5 125$dbh->commit if $dbh;
126
2c631ee0 127use Data::Dumper;
128warn Dumper(\$x);
129warn Dumper(\%seqn2node);
130
131=for
132SV(PVAV) fill=1/1 [#1 @0]
133: +64 sv =64
134: +16 av_max =80
135: AVelem-> [#2 @1]
136: : SV(RV) [#3 @2]
137: : : +24 sv =104
138: : : RV-> [#4 @3]
139: : : : SV(PVAV) fill=-1/-1 [#5 @4]
140: : : : : +64 sv =168
141: AVelem-> [#6 @1]
142: : SV(IV) [#7 @2]
143: : : +24 sv =192
144192 at -e line 1.
145=cut
146__DATA__
147N 1 0 SV(PVAV) fill=1/1
148L 1 64 sv
149L 1 16 av_max
150N 2 1 AVelem->
151N 3 2 SV(RV)
152L 3 24 sv
153N 4 3 RV->
154N 5 4 SV(PVAV) fill=-1/-1
155L 5 64 sv
156N 6 1 AVelem->
157N 7 2 SV(IV)
158L 7 24 sv