Developer Tools

vprofiler

Runs venutian profile on a program and shows where its time goes.

Released v1.0.0 · 2026-09-28
Import
use "stdlib/profiler.ven"

Runs a program under venutian profile and reads back the result, so you can see where its time goes.

vprofiler.ven
result = run_target_profile("bin/venutian", "examples/loop.ven", [])
print map_get(result, "exit_code")
Reference (28 functions)

API reference

run_target_profile(venutian_binary, path, extra_args)

Runs a target program under the profiler and returns the raw process result, unparsed.

result = run_target_profile("bin/venutian", "examples/loop.ven", [])
print map_get(result, "exit_code")

parse_profile_report(stdout_text)

Parses a printed venutian profile report into structured rows.

rows = parse_profile_report(map_get(result, "stdout"))
print length(rows)

profile_program(venutian_binary, path)

Profiles a program with no extra command-line arguments and returns its parsed rows directly, the module's simplest end-to-end entry point: run, then parse, in one call.

rows = profile_program("bin/venutian", "stdlib/tests/fixtures/vprofiler_two_funcs.ven")
print length(rows)

profile_program_with_args(venutian_binary, path, extra_args)

Profiles a program, forwarding extra_args to the profiled process itself, and returns its parsed rows.

rows = profile_program_with_args("bin/venutian", "examples/loop.ven", ["10000"])
print total_calls(rows)

total_time(rows)

The combined "total_time" across every row, the sum used as the denominator for every percentage this module computes.

print total_time(rows)

total_calls(rows)

The combined "calls" count across every row.

print total_calls(rows)

sorted_by_key_descending(rows, key_fn)

Sorts rows by a caller-supplied numeric key, largest first, without mutating the original List.

ranked = sorted_by_key_descending(rows, make(row) give map_get(row, "calls"))

top_n_by_time(rows, n)

The n rows with the greatest "total_time", ranked descending.

slowest_two = top_n_by_time(rows, 2)
print map_get(slowest_two[0], "name")

top_n_by_calls(rows, n)

The n rows with the greatest "calls" count, ranked descending.

busiest_two = top_n_by_calls(rows, 2)
print map_get(busiest_two[0], "name")

top_n_by_per_call(rows, n)

The n rows with the greatest "per_call" time, ranked descending, useful for spotting a function that is called rarely but is expensive each time, which top_n_by_time and top_n_by_calls alone would not surface.

print map_get(top_n_by_per_call(rows, 1)[0], "name")

slowest_function(rows)

The single row with the greatest "total_time".

slow = slowest_function(rows)
print map_get(slow, "name")

most_called_function(rows)

The single row with the greatest "calls" count.

most = most_called_function(rows)
print map_get(most, "name")

row_with_percentage(row, total)

A copy of row with its share of total added as "percentage".

annotated = row_with_percentage(rows[0], total_time(rows))
print map_get(annotated, "percentage")

with_percentage(rows)

Annotates every row with its share of the combined "total_time".

pct = with_percentage(rows)
print map_get(pct[0], "percentage")

hotspots(rows, min_percentage)

The rows whose share of total time is at least min_percentage, ranked highest first.

hot = hotspots(rows, 50.0)
print length(hot)

find_row_by_name(rows, name)

The first row in rows whose "name" matches name.

row = find_row_by_name(rows, "fib")
print map_get(row, "calls")

unique_function_names(before_rows, after_rows)

Every distinct function name across two profiled-row Lists, in the order each name is first seen (every name from before_rows first, then any name found only in after_rows).

names = unique_function_names(before_rows, after_rows)
print length(names)

compare_profiles(before_rows, after_rows)

before_rows = profile_program(bin, "before.ven")
after_rows = profile_program(bin, "after.ven")
comparison = compare_profiles(before_rows, after_rows)
print map_get(comparison[0], "name")

compare_one_function(before_rows, after_rows, name)

Builds a single function's before/after timing and call-count comparison.

c = compare_one_function(before_rows, after_rows, "fib")
print map_get(c, "time_delta")

time_of(row)

print time_of(find_row_by_name(rows, "missing_function"))

calls_of(row)

print calls_of(find_row_by_name(rows, "missing_function"))

format_number(value, digits)

Rounds value to digits decimal places and renders it as Text, the shared number formatting every report table in this module builds its columns from.

print format_number(3.14159, 2)

format_report(rows)

Renders a plain-text, column-aligned report table of every row, ranked by "total_time" descending.

print format_report(rows)

pad_right(text, width, fill)

print pad_right("fib", 8, " ") + "|"

pad_left(text, width, fill)

print "|" + pad_left("42", 8, " ")

repeated_text(piece, count)

Repeats piece count times, concatenated together, the shared building block both padding functions and the ASCII bar chart use.

print repeated_text("#", 5)

format_report_with_bars(rows, bar_width)

Renders an ASCII bar-chart report, one "#"-filled bar per row scaled to its percentage share of total time.

print format_report_with_bars(rows, 20)

format_comparison(comparisons)

Renders a plain-text, column-aligned table of before/after/delta timings from compare_profiless output, the human-readable form of a before/after regression check.

print format_comparison(comparison)

Get notified when vprofiler changes

Get notified about

New versions and security advisories.

New and updated packages, once a day.

News on the math model built in Venutian.