Skip to content

profile_time(): time a block's script and geometry, or an expression - #236

Merged
revarbat merged 1 commit into
mainfrom
feat/profile-time
Oct 6, 2026
Merged

revarbat merged 1 commit into
mainfrom
feat/profile-time

Conversation

@revarbat

@revarbat revarbat commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Evaluator half of profile_time(). Needs BelfrySCAD/openscad_cpp_parser#14 (the submodule points at its commit).

Behaviour

profile_time("gears") { ... }      // PROFILE: gears: 18.39 ms (script 351.8 µs, geometry 18.04 ms)
x = profile_time("fib") fib(18);   // PROFILE: fib: 2.12 ms   -- x is fib(18)'s value
  • Label optional (positional or label=); default line N of file. Evaluated before the clock starts.
  • Under 1 ms prints in µs.
  • Re-render from the ManifoldCache: geometry cached — also when the hit is on an ancestor, which never visits the profile_time() node.
  • Resolve-only run (evaluate(generate=false)): script S (no geometry built).
  • supported_feature("profile-time") = 1.

Implementation

  • Script time: around the resolve call in evalModularCall; stored on CSGNode::profileScriptMs, not in cacheKey().
  • Geometry time: generateTreeImpl, from before the cache lookup. Ancestor hits walk the subtree via reportCachedProfiles, only when the run resolved any profile_time() (profileNodeCount_), so other models pay nothing.
  • Expression form: evalProfileTimeExpr; the bytecode compiler has no case, so a containing function falls back to the interpreter; deliberately absent from simplifyTailStep.
  • Coverage and closure-format dispatch added. PROFILE: lines go to the echo callback directly, never into cached warnings (a replay would print a stale time).
  • Docs: CLAUDE.md § profile_time().

Testing

  • tests/test_profile_time.cpp (11): value passthrough, inside a function, default label, module form both times, named label, cache hit, ancestor cache hit, resolve-only, feature flag, VM forced on, µs formatting. C++ suite 2040/2040.
  • Binding tests 62/62; BelfrySCAD suite 2228 passed against this build; checked in the BelfrySCAD console.
  • BOSL2 docsgen A/B still to run before this ships in a release.

🤖 Generated with Claude Code

profile_time([label]) { ... } prints
  PROFILE: label: T (script S, geometry G)
and x = profile_time([label]) expr; prints PROFILE: label: T and
evaluates to expr's value. Times under 1 ms print in microseconds.

Script time is taken around the resolve call in evalModularCall and
kept on CSGNode::profileScriptMs, outside cacheKey() so profiling never
defeats the ManifoldCache. Geometry time is taken in generateTreeImpl
from before the cache lookup, so a hit reports 'geometry cached'; a hit
on an ancestor walks its subtree for profile_time() nodes (only when
the run has any). A resolve-only run reports script time alone. The
expression form is interpreter-only (NotCompilable) and kept out of
simplifyTailStep so the clock stops after the body. PROFILE lines go
straight to the echo callback, never into cached warnings.

supported_feature("profile-time") is 1. Parser: openscad_cpp_parser
#14 (submodule bumped to it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@revarbat
revarbat merged commit c51b76e into main Oct 6, 2026
3 checks passed
@revarbat
revarbat deleted the feat/profile-time branch October 6, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant