Skip to content

execution: add compilation=true mode for benchmarking compile time#421

Draft
IanButterworth wants to merge 1 commit intomainfrom
ib/compilation_benchmarking
Draft

execution: add compilation=true mode for benchmarking compile time#421
IanButterworth wants to merge 1 commit intomainfrom
ib/compilation_benchmarking

Conversation

@IanButterworth
Copy link
Copy Markdown
Member

@IanButterworth IanButterworth commented Apr 17, 2026

Developed with Claude. Functional but not closely reviewed yet.

Requires JuliaLang/julia@4c7c3e9


Add a compilation::Bool parameter to Parameters that, when enabled, invalidates the target call's entry-point MethodInstance between samples and records the resulting compile time via Base.cumulative_compile_time_ns. Each Trial now carries a compiletimes vector alongside times/gctimes, accessible via compiletime(t), with compile stats rendered in the show output.

Samples dispatch through Base.invokelatest so the direct call site baked into the generated samplefunc is bypassed — invalidate_calls caps the CodeInstance's max_world but does not propagate to backedges, so a devirtualized call would otherwise keep using the stale fptr. evals is forced to 1 in this mode since repeated evaluations would amortize compilation away.

Relies on Base.record_calls / Base.invalidate_calls landing in Julia; guarded via isdefined(Base, :invalidate_calls) in the tests.

Comment thread src/execution.jl
# invalidation caps the CodeInstance but does not
# propagate to backedges (that would defeat the purpose),
# so a devirtualized call would keep using the stale fptr.
__arg_types = Tuple{$([:(Core.Typeof($v)) for v in [quote_vars; setup_vars]]...)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
__arg_types = Tuple{$([:(Core.Typeof($v)) for v in [quote_vars; setup_vars]]...)}
__arg_types = Tuple{
$([:(Core.Typeof($v)) for v in [quote_vars; setup_vars]]...)
}

Comment thread src/parameters.jl
end

const DEFAULT_PARAMETERS = Parameters(5.0, 10000, 1, false, 0, true, false, 0.05, 0.01)
const DEFAULT_PARAMETERS = Parameters(5.0, 10000, 1, false, 0, true, false, 0.05, 0.01, false)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
const DEFAULT_PARAMETERS = Parameters(5.0, 10000, 1, false, 0, true, false, 0.05, 0.01, false)
const DEFAULT_PARAMETERS = Parameters(
5.0, 10000, 1, false, 0, true, false, 0.05, 0.01, false
)

Comment thread src/trials.jl
end

Trial(params::Parameters) = Trial(params, Float64[], Float64[], typemax(Int), typemax(Int))
Trial(params::Parameters) = Trial(params, Float64[], Float64[], Float64[], typemax(Int), typemax(Int))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
Trial(params::Parameters) = Trial(params, Float64[], Float64[], Float64[], typemax(Int), typemax(Int))
function Trial(params::Parameters)
return Trial(params, Float64[], Float64[], Float64[], typemax(Int), typemax(Int))
end

Comment thread src/trials.jl
Comment on lines +17 to +18
Trial(params::Parameters, times::AbstractVector, gctimes::AbstractVector, memory::Integer, allocs::Integer) =
Trial(params, times, gctimes, zeros(Float64, length(times)), memory, allocs)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
Trial(params::Parameters, times::AbstractVector, gctimes::AbstractVector, memory::Integer, allocs::Integer) =
Trial(params, times, gctimes, zeros(Float64, length(times)), memory, allocs)
function Trial(
params::Parameters,
times::AbstractVector,
gctimes::AbstractVector,
memory::Integer,
allocs::Integer,
)
return Trial(params, times, gctimes, zeros(Float64, length(times)), memory, allocs)
end

Comment thread src/trials.jl

function Base.copy(t::Trial)
return Trial(copy(t.params), copy(t.times), copy(t.gctimes), t.memory, t.allocs)
return Trial(copy(t.params), copy(t.times), copy(t.gctimes), copy(t.compiletimes), t.memory, t.allocs)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
return Trial(copy(t.params), copy(t.times), copy(t.gctimes), copy(t.compiletimes), t.memory, t.allocs)
return Trial(
copy(t.params),
copy(t.times),
copy(t.gctimes),
copy(t.compiletimes),
t.memory,
t.allocs,
)

Comment thread src/trials.jl
Base.length(t::Trial) = length(t.times)
function Base.getindex(t::Trial, i::Number)
return push!(Trial(t.params), t.times[i], t.gctimes[i], t.memory, t.allocs)
return push!(Trial(t.params), t.times[i], t.gctimes[i], t.memory, t.allocs, t.compiletimes[i])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
return push!(Trial(t.params), t.times[i], t.gctimes[i], t.memory, t.allocs, t.compiletimes[i])
return push!(
Trial(t.params), t.times[i], t.gctimes[i], t.memory, t.allocs, t.compiletimes[i]
)
end
function Base.getindex(t::Trial, i)
return Trial(t.params, t.times[i], t.gctimes[i], t.compiletimes[i], t.memory, t.allocs)

Comment thread src/trials.jl
return push!(Trial(t.params), t.times[i], t.gctimes[i], t.memory, t.allocs, t.compiletimes[i])
end
Base.getindex(t::Trial, i) = Trial(t.params, t.times[i], t.gctimes[i], t.memory, t.allocs)
Base.getindex(t::Trial, i) = Trial(t.params, t.times[i], t.gctimes[i], t.compiletimes[i], t.memory, t.allocs)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
Base.getindex(t::Trial, i) = Trial(t.params, t.times[i], t.gctimes[i], t.compiletimes[i], t.memory, t.allocs)

Comment thread test/ExecutionTests.jl
compile_bench_target(x) = sum(abs2, x) + prod(x .+ one(eltype(x)))
# Warm up to ensure we exercise the already-compiled path.
compile_bench_target(rand(8))
let t = @benchmark compile_bench_target($(rand(8))) samples=5 seconds=30 compilation=true evals=1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
let t = @benchmark compile_bench_target($(rand(8))) samples=5 seconds=30 compilation=true evals=1
let t = @benchmark compile_bench_target($(rand(8))) samples = 5 seconds = 30 compilation =
true evals = 1

Add a `compilation::Bool` parameter to `Parameters` that, when enabled,
invalidates the target call's entry-point `MethodInstance` between
samples and records the resulting compile time via
`Base.cumulative_compile_time_ns`. Each `Trial` now carries a
`compiletimes` vector alongside `times`/`gctimes`, accessible via
`compiletime(t)`, with compile stats rendered in the `show` output.

Samples dispatch through `Base.invokelatest` so the direct call site
baked into the generated `samplefunc` is bypassed — `invalidate_calls`
caps the `CodeInstance`'s `max_world` but does not propagate to
backedges, so a devirtualized call would otherwise keep using the stale
fptr. `evals` is forced to 1 in this mode since repeated evaluations
would amortize compilation away.

Relies on `Base.record_calls` / `Base.invalidate_calls` landing in
Julia; guarded via `isdefined(Base, :invalidate_calls)` in the tests.

Co-Authored-By: Claude <noreply@anthropic.com>
@IanButterworth IanButterworth force-pushed the ib/compilation_benchmarking branch from 78bb3ef to 4975433 Compare April 17, 2026 03:57
Comment thread src/execution.jl
__gcdiff.bigalloc,
)
__compiletime = __stats.compile_time * 1e9
__sample_ref[] = (__time, __gctime, __memory, __allocs, __compiletime)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
__sample_ref[] = (__time, __gctime, __memory, __allocs, __compiletime)
__sample_ref[] = (
__time, __gctime, __memory, __allocs, __compiletime
)

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