Skip to content

Commit 9baf87e

Browse files
authored
Show the binary bytes we can remove without each export, in --func-metrics (#1379)
* show the binary bytes we can remove without each export, in --func-metrics * check start too
1 parent 155d0b5 commit 9baf87e

File tree

5 files changed

+262
-14
lines changed

5 files changed

+262
-14
lines changed

src/ir/module-utils.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define wasm_ir_module_h
1919

2020
#include "wasm.h"
21+
#include "ir/manipulation.h"
2122

2223
namespace wasm {
2324

@@ -51,6 +52,39 @@ struct BinaryIndexes {
5152
}
5253
};
5354

55+
inline void copyModule(Module& in, Module& out) {
56+
// we use names throughout, not raw points, so simple copying is fine
57+
// for everything *but* expressions
58+
for (auto& curr : in.functionTypes) {
59+
out.addFunctionType(new FunctionType(*curr));
60+
}
61+
for (auto& curr : in.imports) {
62+
out.addImport(new Import(*curr));
63+
}
64+
for (auto& curr : in.exports) {
65+
out.addExport(new Export(*curr));
66+
}
67+
for (auto& curr : in.functions) {
68+
auto* func = new Function(*curr);
69+
func->body = ExpressionManipulator::copy(func->body, out);
70+
out.addFunction(func);
71+
}
72+
for (auto& curr : in.globals) {
73+
out.addGlobal(new Global(*curr));
74+
}
75+
out.table = in.table;
76+
for (auto& segment : out.table.segments) {
77+
segment.offset = ExpressionManipulator::copy(segment.offset, out);
78+
}
79+
out.memory = in.memory;
80+
for (auto& segment : out.memory.segments) {
81+
segment.offset = ExpressionManipulator::copy(segment.offset, out);
82+
}
83+
out.start = in.start;
84+
out.userSections = in.userSections;
85+
out.debugInfoFileNames = in.debugInfoFileNames;
86+
}
87+
5488
} // namespace ModuleUtils
5589

5690
} // namespace wasm

src/passes/Metrics.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <support/colors.h>
2121
#include <wasm.h>
2222
#include <wasm-binary.h>
23+
#include <ir/module-utils.h>
2324

2425
namespace wasm {
2526

@@ -92,7 +93,43 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
9293
counts["[binary-bytes]"] = writer.tableOfContents.functionBodies[i].size;
9394
printCounts(std::string("func: ") + func->name.str);
9495
}
95-
// can't comapre detailed info between passes yet
96+
// print for each export how much code size is due to it, i.e.,
97+
// how much the module could shrink without it.
98+
auto sizeAfterGlobalCleanup = [](Module* module) {
99+
PassRunner runner(module, PassOptions::getWithDefaultOptimizationOptions());
100+
runner.setIsNested(true);
101+
runner.addDefaultGlobalOptimizationPostPasses(); // remove stuff
102+
runner.run();
103+
BufferWithRandomAccess buffer;
104+
WasmBinaryWriter writer(module, buffer);
105+
writer.write();
106+
return buffer.size();
107+
};
108+
size_t baseline;
109+
{
110+
Module test;
111+
ModuleUtils::copyModule(*module, test);
112+
baseline = sizeAfterGlobalCleanup(&test);
113+
}
114+
for (auto& exp : module->exports) {
115+
// create a test module where we remove the export and then see how much can be removed thanks to that
116+
Module test;
117+
ModuleUtils::copyModule(*module, test);
118+
test.removeExport(exp->name);
119+
counts.clear();
120+
counts["[removable-bytes-without-it]"] = baseline - sizeAfterGlobalCleanup(&test);
121+
printCounts(std::string("export: ") + exp->name.str + " (" + exp->value.str + ')');
122+
}
123+
// check how much size depends on the start method
124+
if (!module->start.isNull()) {
125+
Module test;
126+
ModuleUtils::copyModule(*module, test);
127+
test.start = Name();
128+
counts.clear();
129+
counts["[removable-bytes-without-it]"] = baseline - sizeAfterGlobalCleanup(&test);
130+
printCounts(std::string("start: ") + module->start.str);
131+
}
132+
// can't compare detailed info between passes yet
96133
lastMetricsPass = nullptr;
97134
} else {
98135
// add function info
@@ -116,7 +153,10 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
116153
int total = 0;
117154
for (auto i : counts) {
118155
keys.push_back(i.first);
119-
total += i.second;
156+
// total is of all the normal stuff, not the special [things]
157+
if (i.first[0] != '[') {
158+
total += i.second;
159+
}
120160
}
121161
keys.push_back("[total]");
122162
counts["[total]"] = total;
@@ -127,6 +167,7 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
127167
o << title << "\n";
128168
for (auto* key : keys) {
129169
auto value = counts[key];
170+
if (value == 0) continue;
130171
o << " " << left << setw(15) << key << ": " << setw(8)
131172
<< value;
132173
if (lastMetricsPass) {

test/passes/func-metrics.txt

Lines changed: 115 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,23 @@ global
22
[funcs] : 3
33
[memory-data] : 9
44
[table-data] : 3
5-
[total] : 18
5+
[total] : 3
66
const : 3
77
func: empty
88
[binary-bytes] : 3
9-
[total] : 4
10-
[vars] : 0
9+
[total] : 1
1110
nop : 1
1211
func: small
1312
[binary-bytes] : 9
14-
[total] : 14
15-
[vars] : 0
13+
[total] : 5
1614
block : 1
1715
const : 1
1816
drop : 1
1917
nop : 1
2018
return : 1
2119
func: ifs
2220
[binary-bytes] : 51
23-
[total] : 76
21+
[total] : 24
2422
[vars] : 1
2523
binary : 1
2624
block : 1
@@ -86,7 +84,116 @@ func: ifs
8684
)
8785
)
8886
global
89-
[funcs] : 0
90-
[total] : 0
9187
(module
9288
)
89+
global
90+
[funcs] : 3
91+
func: func_a
92+
[binary-bytes] : 16
93+
[total] : 8
94+
block : 1
95+
call : 2
96+
call_import : 5
97+
func: func_b
98+
[binary-bytes] : 22
99+
[total] : 11
100+
block : 1
101+
call_import : 10
102+
func: func_c
103+
[binary-bytes] : 32
104+
[total] : 16
105+
block : 1
106+
call_import : 15
107+
export: a (func_a)
108+
[removable-bytes-without-it]: 72
109+
export: b (func_b)
110+
[removable-bytes-without-it]: 18
111+
(module
112+
(type $FUNCSIG$v (func))
113+
(import "env" "waka" (func $waka))
114+
(export "a" (func $func_a))
115+
(export "b" (func $func_b))
116+
(func $func_a (; 1 ;) (type $FUNCSIG$v)
117+
(call $waka)
118+
(call $waka)
119+
(call $waka)
120+
(call $waka)
121+
(call $waka)
122+
(call $func_b)
123+
(call $func_c)
124+
)
125+
(func $func_b (; 2 ;) (type $FUNCSIG$v)
126+
(call $waka)
127+
(call $waka)
128+
(call $waka)
129+
(call $waka)
130+
(call $waka)
131+
(call $waka)
132+
(call $waka)
133+
(call $waka)
134+
(call $waka)
135+
(call $waka)
136+
)
137+
(func $func_c (; 3 ;) (type $FUNCSIG$v)
138+
(call $waka)
139+
(call $waka)
140+
(call $waka)
141+
(call $waka)
142+
(call $waka)
143+
(call $waka)
144+
(call $waka)
145+
(call $waka)
146+
(call $waka)
147+
(call $waka)
148+
(call $waka)
149+
(call $waka)
150+
(call $waka)
151+
(call $waka)
152+
(call $waka)
153+
)
154+
)
155+
global
156+
[funcs] : 1
157+
func: func_a
158+
[binary-bytes] : 12
159+
[total] : 6
160+
block : 1
161+
call_import : 5
162+
export: a (func_a)
163+
[removable-bytes-without-it]: 7
164+
start: func_a
165+
[removable-bytes-without-it]: 3
166+
(module
167+
(type $FUNCSIG$v (func))
168+
(import "env" "waka" (func $waka))
169+
(export "a" (func $func_a))
170+
(start $func_a)
171+
(func $func_a (; 1 ;) (type $FUNCSIG$v)
172+
(call $waka)
173+
(call $waka)
174+
(call $waka)
175+
(call $waka)
176+
(call $waka)
177+
)
178+
)
179+
global
180+
[funcs] : 1
181+
func: func_a
182+
[binary-bytes] : 12
183+
[total] : 6
184+
block : 1
185+
call_import : 5
186+
start: func_a
187+
[removable-bytes-without-it]: 67
188+
(module
189+
(type $FUNCSIG$v (func))
190+
(import "env" "waka" (func $waka))
191+
(start $func_a)
192+
(func $func_a (; 1 ;) (type $FUNCSIG$v)
193+
(call $waka)
194+
(call $waka)
195+
(call $waka)
196+
(call $waka)
197+
(call $waka)
198+
)
199+
)

test/passes/func-metrics.wast

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,72 @@
5454
;; module with no table or memory or anything for that matter
5555
(module
5656
)
57+
;; export size checking
58+
(module
59+
(import "env" "waka" (func $waka))
60+
(export "a" (func $func_a))
61+
(export "b" (func $func_b))
62+
(func $func_a
63+
(call $waka)
64+
(call $waka)
65+
(call $waka)
66+
(call $waka)
67+
(call $waka)
68+
(call $func_b)
69+
(call $func_c)
70+
)
71+
(func $func_b
72+
(call $waka)
73+
(call $waka)
74+
(call $waka)
75+
(call $waka)
76+
(call $waka)
77+
(call $waka)
78+
(call $waka)
79+
(call $waka)
80+
(call $waka)
81+
(call $waka)
82+
)
83+
(func $func_c
84+
(call $waka)
85+
(call $waka)
86+
(call $waka)
87+
(call $waka)
88+
(call $waka)
89+
(call $waka)
90+
(call $waka)
91+
(call $waka)
92+
(call $waka)
93+
(call $waka)
94+
(call $waka)
95+
(call $waka)
96+
(call $waka)
97+
(call $waka)
98+
(call $waka)
99+
)
100+
)
101+
;; start size checking
102+
(module
103+
(import "env" "waka" (func $waka))
104+
(export "a" (func $func_a))
105+
(start $func_a)
106+
(func $func_a
107+
(call $waka)
108+
(call $waka)
109+
(call $waka)
110+
(call $waka)
111+
(call $waka)
112+
)
113+
)
114+
(module
115+
(import "env" "waka" (func $waka))
116+
(start $func_a)
117+
(func $func_a
118+
(call $waka)
119+
(call $waka)
120+
(call $waka)
121+
(call $waka)
122+
(call $waka)
123+
)
124+
)
125+

test/passes/metrics.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ total
22
[funcs] : 1
33
[memory-data] : 9
44
[table-data] : 3
5-
[total] : 41
5+
[total] : 27
66
[vars] : 1
77
binary : 1
88
block : 1
@@ -57,8 +57,5 @@ total
5757
)
5858
)
5959
total
60-
[funcs] : 0
61-
[total] : 0
62-
[vars] : 0
6360
(module
6461
)

0 commit comments

Comments
 (0)