... | ... |
@@ -3,28 +3,41 @@ |
3 | 3 |
use strict; |
4 | 4 |
use warnings; |
5 | 5 |
|
6 |
-# usage poolsize.pl < mpool_spamfile |
|
6 |
+use constant PERM => 0; |
|
7 |
+use constant TEMP => 1; |
|
8 |
+use constant MAXA => 2; |
|
9 |
+use constant REAS => 3; |
|
10 |
+ |
|
11 |
+use constant TAKE => PERM; |
|
12 |
+ |
|
13 |
+# usage poolsize.pl < mpool_allocfile |
|
7 | 14 |
|
8 | 15 |
my $sizeof_void_ptr; |
9 | 16 |
my $overhead = 0; |
10 | 17 |
|
11 | 18 |
my %ptrs; |
12 | 19 |
my %sizes; |
20 |
+my %maxes; |
|
13 | 21 |
|
14 | 22 |
my $maxsz = 0; |
15 | 23 |
|
24 |
+print STDERR "Parsing allocations...\n"; |
|
16 | 25 |
while(<>) { |
17 | 26 |
if(/malloc @(0x[0-9a-z]+) size (\d+) \((.*)\)/) { |
18 | 27 |
die "ptr $1 re-malloc" if defined $ptrs{$1}; |
19 | 28 |
$ptrs{$1} = $2; |
20 |
- $sizes{$ptrs{$1}} = [0, 0, ''] unless defined $sizes{$ptrs{$1}}; |
|
29 |
+ $sizes{$ptrs{$1}} = [0, 0, 0, 'UNUSED'] unless defined $sizes{$ptrs{$1}}; |
|
30 |
+ $maxes{$ptrs{$1}} = [0, 0] unless defined $maxes{$ptrs{$1}}; |
|
31 |
+ $maxes{$ptrs{$1}}[0]++; |
|
32 |
+ $maxes{$ptrs{$1}}[1] = $maxes{$ptrs{$1}}[0] unless $maxes{$ptrs{$1}}[1] >= $maxes{$ptrs{$1}}[0]; |
|
21 | 33 |
$maxsz = $2 unless $maxsz >= $2; |
22 | 34 |
$overhead++ if $3 eq 'new map'; |
23 | 35 |
next; |
24 | 36 |
} |
25 | 37 |
if(/free @(0x[0-9a-z]+)/) { |
26 | 38 |
die "ptr $1 invalid free" unless defined $ptrs{$1}; |
27 |
- $sizes{$ptrs{$1}}[0]++; |
|
39 |
+ $sizes{$ptrs{$1}}[TEMP]++; |
|
40 |
+ $maxes{$ptrs{$1}}[0]--; |
|
28 | 41 |
delete $ptrs{$1}; |
29 | 42 |
next; |
30 | 43 |
} |
... | ... |
@@ -37,10 +50,13 @@ while(<>) { |
37 | 37 |
} |
38 | 38 |
|
39 | 39 |
$overhead *= $sizeof_void_ptr; |
40 |
+print STDERR "Parsing complete (size overhead = $overhead)\n"; |
|
40 | 41 |
|
41 |
-foreach (keys %ptrs) { |
|
42 |
- $sizes{$ptrs{$_}}[1]++; |
|
43 |
-} |
|
42 |
+$sizes{$ptrs{$_}}[PERM]++ foreach (keys %ptrs); |
|
43 |
+undef %ptrs; |
|
44 |
+ |
|
45 |
+$sizes{$_}[MAXA] = $maxes{$_}[1] foreach (keys %maxes); |
|
46 |
+undef %maxes; |
|
44 | 47 |
|
45 | 48 |
$maxsz |= $maxsz>>16; |
46 | 49 |
$maxsz |= $maxsz>>8; |
... | ... |
@@ -50,31 +66,69 @@ $maxsz |= $maxsz>>1; |
50 | 50 |
$maxsz++; |
51 | 51 |
|
52 | 52 |
while($maxsz) { |
53 |
+ my $nextsz = $maxsz>>1; |
|
53 | 54 |
if(defined $sizes{$maxsz}) { |
54 |
- $sizes{$maxsz}[2] = 'POW2'; |
|
55 |
+ $sizes{$maxsz}[REAS] = 'POW2'; |
|
55 | 56 |
} else { |
56 |
- $sizes{$maxsz} = [0, 0, 'POW2']; |
|
57 |
+ $sizes{$maxsz} = [0, 0, 0, 'POW2']; |
|
57 | 58 |
} |
58 |
- $maxsz>>=1; |
|
59 |
-} |
|
60 |
- |
|
61 |
-my $grp_size = 0; |
|
62 |
-foreach (sort { $b <=> $a } keys %sizes) { |
|
63 |
- my $count = $sizes{$_}[1]; |
|
64 |
- my $score = ($grp_size - $_) * $count - $overhead; |
|
65 |
- $score = 0 unless $grp_size != 0; |
|
59 |
+ my $nextpow2 = $nextsz; |
|
60 |
+ while(1) { |
|
61 |
+ my $refsz = $maxsz; |
|
62 |
+ my @group; |
|
63 |
+ foreach (sort { $b <=> $a } keys %sizes) { |
|
64 |
+ next unless $_ > $nextpow2; |
|
65 |
+ next unless $_ <= $maxsz; |
|
66 |
+ next unless ($sizes{$_}[TAKE] > 0 || $_ == $maxsz); |
|
67 |
+ $nextsz = $_; |
|
68 |
+ last unless ($refsz - $_) * $sizes{$_}[TAKE] <= $overhead; |
|
69 |
+ $refsz = $_; |
|
70 |
+ push @group, $_; |
|
71 |
+ } |
|
72 |
+ while($#group >= 23) { |
|
73 |
+ my $items = $#group / 2; |
|
74 |
+ $nextsz = $group[$items + 1]; |
|
75 |
+ @group = @group[0..$items]; |
|
76 |
+ } |
|
77 |
+ print STDERR "Processing group $maxsz -> $nextsz (count ".($#group + 1).")\n"; |
|
78 |
+ my @topscore; # 0 => score | 1 => used bits | origbits |
|
79 |
+ for(my $origbits = 0; $origbits < 1<<$#group ; $origbits++) { |
|
80 |
+ my $bits = $origbits; |
|
81 |
+ my $bitcnt = 0; |
|
82 |
+ my $score = $overhead; |
|
83 |
+ my $grp_size = $maxsz; |
|
66 | 84 |
|
67 |
- if($score >= 0 || $sizes{$_}[2] eq 'POW2') { |
|
68 |
- $grp_size = $_; |
|
69 |
- if($score >=0) { |
|
70 |
- $sizes{$_}[2] = $sizes{$_}[2] eq 'POW2' ? 'USE/POW2' : 'USE'; |
|
85 |
+ printf STDERR "%3i%%\r", $origbits * 100 / (1<<$#group) unless ($origbits & 1); |
|
86 |
+ for (my $i = 1; $i<= $#group; $i++) { |
|
87 |
+ if($bits & 1) { |
|
88 |
+ $score += $overhead + $sizes{$group[$i]}[TAKE] * $group[$i]; |
|
89 |
+ $bitcnt++; |
|
90 |
+ $grp_size = $group[$i]; |
|
91 |
+ } else { |
|
92 |
+ $score += $sizes{$group[$i]}[TAKE] * $grp_size; |
|
93 |
+ } |
|
94 |
+ $bits>>=1; |
|
95 |
+ } |
|
96 |
+ if(!defined $topscore[0] || $score < $topscore[0] || ($score == $topscore[0] && $bitcnt > $topscore[1])) { |
|
97 |
+ @topscore = ($score, $bitcnt, $origbits); |
|
98 |
+ } |
|
71 | 99 |
} |
72 |
- } else { |
|
73 |
- $sizes{$_}[2] = 'GROUP'; |
|
100 |
+ my $bits = ($topscore[2]<<1) | 1; |
|
101 |
+ for (my $i = 0; $i<=$#group; $i++) { |
|
102 |
+ if ($bits & 1) { |
|
103 |
+ $sizes{$group[$i]}[REAS] = "USE"; |
|
104 |
+ } else { |
|
105 |
+ $sizes{$group[$i]}[REAS] = "GROUP"; |
|
106 |
+ } |
|
107 |
+ $bits>>=1; |
|
108 |
+ } |
|
109 |
+ last unless $nextsz < $maxsz; |
|
110 |
+ $maxsz = $nextsz; |
|
74 | 111 |
} |
112 |
+ $maxsz = $nextpow2; |
|
75 | 113 |
} |
76 | 114 |
|
77 |
-print "/* SIZE PERM TEMP ACT! */\n"; |
|
115 |
+print "/* SIZE PERM TEMP MAX ACT! */\n"; |
|
78 | 116 |
foreach (sort { $a <=> $b } keys %sizes) { |
79 |
- printf "%7u, /* %7u %7u %8s */\n", $_, $sizes{$_}[1], $sizes{$_}[0], $sizes{$_}[2]; |
|
117 |
+ printf "%7u, /* %7u %7u %7u %8s */\n", $_, $sizes{$_}[PERM], $sizes{$_}[TEMP], $sizes{$_}[MAXA], $sizes{$_}[REAS]; |
|
80 | 118 |
} |