Counting A WebAssembly Module
wasm-counts.wasm turns a WebAssembly module into deterministic long-form
CSV. It reports factual static counts for comparing builds; it does not assign
a score or decide whether a module is acceptable.
make -j qip components/application/wasm/wasm-counts.wasm
qip run \
-i components/utf8/e164.wasm \
-- components/application/wasm/wasm-counts.wasm
The output has one integer measurement per row:
metric,value
module_bytes,304
functions_defined,5
functions_imported,0
instructions,75
loops,1
branches,5
simd_instructions,0
Rows are always emitted in the same order, including zero values. This makes
the output useful with diff, spreadsheets, and databases without treating a
missing row as zero.
What It Counts #
The report covers module structure, functions, control flow, calls, SIMD,
declared memory, data segments, and instructions that can trap directly based
on their operands or bounds.
loops counts structured loop instructions.
branches counts br, br_if, and br_table instructions.
conditional_branches counts if, br_if, and br_table instructions.
simd_instructions counts instructions in the SIMD opcode space.
v128_types counts v128 occurrences in function and global types.
potentially_trapping_instructions combines explicit traps, integer
division and remainder, trapping float-to-integer conversion, bounded
memory and table operations, and indirect or reference calls.
The trapping count describes instruction sites, not executions. A load that
is provably in bounds still counts, while an ordinary direct call does not
count merely because its callee might trap.
Memory rows report declared capacity and initial data. They do not measure
allocator use, working set, stack depth, or peak memory; those require running
or instrumenting the module.
Load It Into SQLite #
SQLite's shell can import the output directly:
qip run -i a.wasm -- components/application/wasm/wasm-counts.wasm > a.csv
sqlite3 counts.db
Then use the shell's CSV mode:
.mode csv
.headers on
CREATE TABLE a_counts (metric TEXT PRIMARY KEY, value INTEGER NOT NULL);
.import --skip 1 a.csv a_counts
SELECT * FROM a_counts WHERE metric IN ('loops', 'branches', 'simd_instructions');
For comparisons across many modules, add the module name as a column while
loading each file into a shared (module, metric, value) table.
When Not To Use It #
Use WABT's wasm-stats when you need a full frequency table for every opcode
and immediate value. Use runtime profiling when you need to know which code is
hot or how much memory an execution actually touches. Counts alone do not
predict either result.