tyc profile
tyc profile [PATH] [--out DIR]Runs the normal tyc build pipeline, then post-processes every emitted .py so each top-level function records its call count and cumulative wall-clock time. When the instrumented program exits, an atexit hook writes the counters to typhon-profile.json. That file feeds [strictness] pgo-memoise, which promotes hot pure functions to @functools.cache on the next build.
tyc profile does not run the program — it only produces the instrumented build. You run the emitted entry point yourself with a representative workload.
Examples
tyc profile # instrumented build → build/python build/main.py --bench # run it; typhon-profile.json is written on exittyc build # with pgo-memoise = true, hot pure fns are now cached
tyc profile --out dist/ # instrument into dist/ instead of the configured out dirTYPHON_PROFILE_OUT=/tmp/p.json python build/main.py # write the profile somewhere elseRun the instrumented program from the project root: the profile is written to the process’s working directory (or to TYPHON_PROFILE_OUT), and tyc build reads typhon-profile.json from the directory that holds typhon.toml.
What the profile contains
A JSON object keyed by <module>.<qualname>, exactly as Python’s fn.__module__ and fn.__qualname__ report them:
{ "__main__.parse_port": { "calls": 12483, "total_seconds": 0.0084 }, "users.find_user": { "calls": 4521, "total_seconds": 0.1249 }}The entry module runs as __main__, so its functions are recorded as __main__.<fn>; every other module is keyed by its dotted module name (pkg.sub.helpers.<fn>).
Using the profile
Enable PGO in typhon.toml (or set [optimise] level = 1, which flips the default):
[strictness]pgo-memoise = truepgo-min-calls = 100 # threshold; default 100On the next tyc build, every function that passes the purity analysis and whose recorded call count meets pgo-min-calls is promoted to @functools.cache — even if you didn’t write @memo. This complements auto-memoise (which caches every pure function regardless of hot-ness). A function already carrying @memo is never double-decorated.
The match is per module: a users.find_user sample only ever promotes find_user in src/users.ty, never a same-named function elsewhere. For the entry module both the __main__.<fn> spelling the profiler writes and the main.<fn> spelling are accepted, so the round trip works for src/main.ty out of the box. A bare <fn> key with no module qualifier matches by name, as a fallback for profiles produced by other tools.
Missing profile file
Not an error — and not a warning either; PGO is best-effort. With pgo-memoise = true and no typhon-profile.json, tyc build simply promotes nothing and falls through to the explicit @memo / auto-memoise paths.
Recommended workflow
- Write a “representative” entry point (e.g. a benchmark or a CLI invocation that exercises hot paths).
tyc profile, then run the instrumented program from the project root.- Commit
typhon-profile.json(or generate it in CI). tyc buildwithpgo-memoise = true.
PGO is purely additive — functions promoted by PGO behave the same as ones you marked @memo manually. They get cached; their purity is verified at build time.
What’s profiled
Every top-level def / async def in the project’s emitted modules — not class or impl methods, not closures inside other functions, and not the generated typhon_runtime/ helpers. Broadening the surface is a follow-up.
Flags
| Flag | Default | Effect |
|---|---|---|
PATH | . | Project directory. |
--out DIR (-o) | [project] out | Output directory for the instrumented build, forwarded to tyc build. |
Where the profile lands is controlled at run time by the TYPHON_PROFILE_OUT environment variable (default typhon-profile.json in the working directory), not by a tyc profile flag.
Where next
@pureand@memo— the purity check used for PGO eligibility.[strictness] pgo-memoise— config knob.