From 062720aff660d22c7f173b505a1c7e24c55b3997 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 2 Apr 2025 03:16:27 -0500 Subject: [PATCH 1/2] Ensure compilation happens after logging starts If compilation of the workload happens before the logging system is initialized, many CodeInstances may be missed. This exploits `Core.@invokelatest` to prevent inference from proceeding into the workload. It removes the `@force_compile`, which introduces some risk that even the workload will be interpreted. Also wraps the `@setup_workload` block with a `let`. Fixes #17 Fixes #26 Fixes #37 --- .gitignore | 1 + Project.toml | 6 ++- src/workloads.jl | 10 +++-- test/AliasTables/Manifest.toml | 51 ++++++++++++++++++++++++++ test/AliasTables/Project.toml | 11 ++++++ test/AliasTables/src/AliasTables.jl | 18 +++++++++ test/MSort/Manifest.toml | 42 +++++++++++++++++++++ test/MSort/Project.toml | 7 ++++ test/MSort/src/MSort.jl | 57 +++++++++++++++++++++++++++++ test/runtests.jl | 19 ++++++++++ 10 files changed, 217 insertions(+), 5 deletions(-) create mode 100644 test/AliasTables/Manifest.toml create mode 100644 test/AliasTables/Project.toml create mode 100644 test/AliasTables/src/AliasTables.jl create mode 100644 test/MSort/Manifest.toml create mode 100644 test/MSort/Project.toml create mode 100644 test/MSort/src/MSort.jl diff --git a/.gitignore b/.gitignore index 20fe29d..b5ac9c8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.jl.mem /Manifest.toml /docs/build/ +.vscode/ \ No newline at end of file diff --git a/Project.toml b/Project.toml index 34a5224..89882f7 100644 --- a/Project.toml +++ b/Project.toml @@ -1,19 +1,21 @@ name = "PrecompileTools" uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -authors = ["Tim Holy ", "t-bltg ", "and contributors"] version = "1.3.0" +authors = ["Tim Holy ", "t-bltg ", "and contributors"] [deps] Preferences = "21216c6a-2e73-6563-6e65-726566657250" [compat] +InteractiveUtils = "1.11.0" Preferences = "1" julia = "1.12" [extras] +InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [targets] -test = ["Pkg", "Test", "UUIDs"] +test = ["InteractiveUtils", "Pkg", "Test", "UUIDs"] diff --git a/src/workloads.jl b/src/workloads.jl index 806f1f9..0cc669e 100644 --- a/src/workloads.jl +++ b/src/workloads.jl @@ -12,6 +12,8 @@ function workload_enabled(mod::Module) end end +@noinline is_generating_output() = ccall(:jl_generating_output, Cint, ()) == 1 + function tag_newly_inferred_enable() ccall(:jl_tag_newly_inferred_enable, Cvoid, ()) if !Base.generating_output() # for verbose[] @@ -60,10 +62,10 @@ end - indirect runtime-dispatched calls to such methods. """ macro compile_workload(ex::Expr) - local iscompiling = :((ccall(:jl_generating_output, Cint, ()) == 1 && $PrecompileTools.workload_enabled(@__MODULE__))) + local iscompiling = :($PrecompileTools.is_generating_output() && $PrecompileTools.workload_enabled(@__MODULE__)) ex = quote begin - Base.Experimental.@force_compile + Core.@latestworld # block inference from proceeding beyond this point (xref https://github.com/JuliaLang/julia/issues/57957) $(esc(ex)) end end @@ -110,7 +112,9 @@ macro setup_workload(ex::Expr) # trigger inference & codegen in undesirable ways (see #16). return quote if $iscompiling || $PrecompileTools.verbose[] - $(esc(ex)) + let + $(esc(ex)) + end end end end diff --git a/test/AliasTables/Manifest.toml b/test/AliasTables/Manifest.toml new file mode 100644 index 0000000..6065c23 --- /dev/null +++ b/test/AliasTables/Manifest.toml @@ -0,0 +1,51 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.12.0-DEV" +manifest_format = "2.0" +project_hash = "08b5cd69f1c3c631130172e148f3d7bf0afe42df" + +[[deps.AliasTables]] +deps = ["PrecompileTools"] +path = "." +uuid = "beccad7b-8a6a-4466-a02c-5791472d17ea" +version = "0.1.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +version = "1.11.0" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +path = "../.." +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.3.0" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +version = "1.11.0" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" diff --git a/test/AliasTables/Project.toml b/test/AliasTables/Project.toml new file mode 100644 index 0000000..6eeaad7 --- /dev/null +++ b/test/AliasTables/Project.toml @@ -0,0 +1,11 @@ +name = "AliasTables" +uuid = "beccad7b-8a6a-4466-a02c-5791472d17ea" +version = "0.1.0" +authors = ["Tim Holy "] + +[deps] +PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[compat] +Random = "1.11.0" diff --git a/test/AliasTables/src/AliasTables.jl b/test/AliasTables/src/AliasTables.jl new file mode 100644 index 0000000..9060ecb --- /dev/null +++ b/test/AliasTables/src/AliasTables.jl @@ -0,0 +1,18 @@ +module AliasTables + +using Random +using PrecompileTools + +export AliasTable + +struct AliasTable{T} + x::T +end +Base.rand(x::AliasTable) = rand(x.x) + +PrecompileTools.@compile_workload begin + at = AliasTable([1.0, 2.0]) + rand(at) +end + +end diff --git a/test/MSort/Manifest.toml b/test/MSort/Manifest.toml new file mode 100644 index 0000000..f613e09 --- /dev/null +++ b/test/MSort/Manifest.toml @@ -0,0 +1,42 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.12.0-DEV" +manifest_format = "2.0" +project_hash = "54196cb61d86afd465157edc4da76dcf0e248920" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +version = "1.11.0" + +[[deps.MSort]] +deps = ["PrecompileTools"] +path = "." +uuid = "75c9a4e7-9bfb-42c4-89fa-37abaaaaefd3" +version = "0.1.0" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +path = "../.." +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.3.0" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +version = "1.11.0" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" diff --git a/test/MSort/Project.toml b/test/MSort/Project.toml new file mode 100644 index 0000000..1b085bd --- /dev/null +++ b/test/MSort/Project.toml @@ -0,0 +1,7 @@ +name = "MSort" +uuid = "75c9a4e7-9bfb-42c4-89fa-37abaaaaefd3" +version = "0.1.0" +authors = ["Tim Holy "] + +[deps] +PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" diff --git a/test/MSort/src/MSort.jl b/test/MSort/src/MSort.jl new file mode 100644 index 0000000..fccb960 --- /dev/null +++ b/test/MSort/src/MSort.jl @@ -0,0 +1,57 @@ +module MSort + +# issue #26 + +using PrecompileTools + +function quicksort( + v::Vector{T}; + lo::Int = 1, + hi::Int = length(v), +) where {T <: Union{Int64, Float64}} + x = copy(v) + quick!(x, lo, hi) + x +end + +function partition( + xp::Vector{T}, + pivot::T, + left::Int, + right::Int, +) where {T <: Union{Int64, Float64}} + while left <= right + while xp[left] < pivot + left += 1 + end + while pivot < xp[right] + right -= 1 + end + if left <= right + xp[left], xp[right] = xp[right], xp[left] + left += 1 + right -= 1 + end + end + left, right +end + +function quick!( + xp::Vector{T}, + i::Int, + j::Int, +) where {T <: Union{Int64, Float64}} + if j > i + left, right = partition(xp, xp[(j+i)>>>1], i, j) + quick!(xp, i, right) + quick!(xp, left, j) + end +end + +@setup_workload begin + @compile_workload begin + quicksort(rand(64)) + end +end + +end diff --git a/test/runtests.jl b/test/runtests.jl index 25451a3..5c8c59f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,6 +2,7 @@ using PrecompileTools using Test using Pkg using UUIDs +using InteractiveUtils using Base: specializations @testset "PrecompileTools.jl" begin @@ -82,6 +83,24 @@ using Base: specializations end PrecompileTools.verbose[] = oldval + using MSort + using AliasTables + x = rand(64) + pipe = Pipe() + oldstderr = stderr + redirect_stderr(pipe) + @trace_compile begin + MSort.quicksort(x) + at = AliasTable([1.0, 2.0]) + rand(at) + end + close(pipe.in) + redirect_stderr(oldstderr) + str = read(pipe.out, String) + @test isempty(str) + + ## @recompile_invalidations + # Mimic the format written to `_jl_debug_method_invalidation` # As a source of MethodInstances, `getproperty` has lots m = which(getproperty, (Any, Symbol)) From e5ec2f63759ecbcfedfc32b4344aa0583c2dfc03 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 2 Apr 2025 04:40:06 -0500 Subject: [PATCH 2/2] Move some tests to run without coverage --- .github/workflows/CI.yml | 1 + test/runtests.jl | 17 ----------------- test/without_coverage.jl | 27 +++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 test/without_coverage.jl diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9120914..6e90189 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -33,6 +33,7 @@ jobs: - uses: julia-actions/cache@v2 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + - run: julia --code-coverage=none --startup=no --project test/without_coverage.jl - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v5 with: diff --git a/test/runtests.jl b/test/runtests.jl index 5c8c59f..f9db701 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,7 +2,6 @@ using PrecompileTools using Test using Pkg using UUIDs -using InteractiveUtils using Base: specializations @testset "PrecompileTools.jl" begin @@ -83,22 +82,6 @@ using Base: specializations end PrecompileTools.verbose[] = oldval - using MSort - using AliasTables - x = rand(64) - pipe = Pipe() - oldstderr = stderr - redirect_stderr(pipe) - @trace_compile begin - MSort.quicksort(x) - at = AliasTable([1.0, 2.0]) - rand(at) - end - close(pipe.in) - redirect_stderr(oldstderr) - str = read(pipe.out, String) - @test isempty(str) - ## @recompile_invalidations # Mimic the format written to `_jl_debug_method_invalidation` diff --git a/test/without_coverage.jl b/test/without_coverage.jl new file mode 100644 index 0000000..2fdeba0 --- /dev/null +++ b/test/without_coverage.jl @@ -0,0 +1,27 @@ +using PrecompileTools +using Test +using InteractiveUtils + +@testset "No-coverage tests" begin + @assert Base.JLOptions().code_coverage == 0 "These tests should be run with coverage disabled" + + push!(LOAD_PATH, @__DIR__) + + using MSort + using AliasTables + x = rand(64) + pipe = Pipe() + oldstderr = stderr + redirect_stderr(pipe) + @trace_compile begin + MSort.quicksort(x) + at = AliasTable([1.0, 2.0]) + rand(at) + end + close(pipe.in) + redirect_stderr(oldstderr) + str = read(pipe.out, String) + @test isempty(str) + + pop!(LOAD_PATH) +end