From 5a503e4e843d1f62fc516c2744fef9e951d1f29e Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 23 Jul 2026 11:27:38 +0200 Subject: [PATCH 1/4] Reduce eltype combinatorics in the #14005 ldiv testset (#738) Co-authored-by: Claude Fable 5 --- test/sparsevector.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/sparsevector.jl b/test/sparsevector.jl index c91f0d69..6c19bc9b 100644 --- a/test/sparsevector.jl +++ b/test/sparsevector.jl @@ -1337,6 +1337,10 @@ end floattypes = (Float32, Float64, BigFloat) complextypes = (ComplexF32, ComplexF64) eltypes = (inttypes..., floattypes..., complextypes...) + # The full eltype cross product compiles thousands of specializations + # (several CI minutes); do it only for the core types and pair the + # remaining eltypes with Float64. + coretypes = (Int64, Float64, ComplexF64) for eltypemat in eltypes (densemat, sparsemat) = eltypemat in inttypes ? (denseintmat, sparseintmat) : @@ -1350,6 +1354,8 @@ end LinearAlgebra.UnitLowerTriangular(sparsemat), LinearAlgebra.UnitUpperTriangular(sparsemat) ) for eltypevec in eltypes + (eltypemat in coretypes && eltypevec in coretypes) || + eltypemat == Float64 || eltypevec == Float64 || continue spvecs = eltypevec in inttypes ? sparseintvecs : eltypevec in floattypes ? sparsefloatvecs : eltypevec in complextypes && sparsecomplexvecs From b2fed2148f43851073e2a4091c2cd78bd9644bd3 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 23 Jul 2026 11:28:07 +0200 Subject: [PATCH 2/4] Run only the Aqua tests in the aqua CI job (#737) Co-authored-by: Claude Fable 5 --- .github/workflows/ci.yml | 7 +++---- test/runtests.jl | 4 ---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1786713e..517fbb56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,10 +68,9 @@ jobs: version: ${{ matrix.julia-version }} arch: ${{ matrix.julia-arch }} - uses: julia-actions/cache@v2 - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 - env: - SPARSEARRAYS_AQUA_TEST: true + - name: Run Aqua and ambiguity tests + run: | + julia --color=yes -e 'using Pkg; Pkg.activate(temp=true); Pkg.develop(path=pwd()); Pkg.add(name="Aqua", version="0.8"); include(joinpath(pwd(), "test", "ambiguous.jl"))' docs: runs-on: ubuntu-latest steps: diff --git a/test/runtests.jl b/test/runtests.jl index 5819db1a..b8bcdbc7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,10 +3,6 @@ using Test, LinearAlgebra, SparseArrays include("util/gha.jl") -if Base.get_bool_env("SPARSEARRAYS_AQUA_TEST", false) - include("ambiguous.jl") -end - include("allowscalar.jl") include("fixed.jl") include("higherorderfns.jl") From 5e1300eed6509138ef1b7768a463f92c7519f6a5 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 23 Jul 2026 12:46:38 +0200 Subject: [PATCH 3/4] Run test files in parallel with ParallelTestRunner (#739) Co-authored-by: Claude Fable 5 --- Project.toml | 4 ++- test/runtests.jl | 79 +++++++++++-------------------------------- test/threads_suite.jl | 36 ++++++++++++++++++++ 3 files changed, 59 insertions(+), 60 deletions(-) create mode 100644 test/threads_suite.jl diff --git a/Project.toml b/Project.toml index f53533f5..273358d8 100644 --- a/Project.toml +++ b/Project.toml @@ -15,6 +15,7 @@ Dates = "<0.0.1, 1" InteractiveUtils = "<0.0.1, 1" Libdl = "<0.0.1, 1" LinearAlgebra = "<0.0.1, 1" +ParallelTestRunner = "2" Pkg = "<0.0.1, 1" Printf = "<0.0.1, 1" Random = "<0.0.1, 1" @@ -27,9 +28,10 @@ julia = "1.11" Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Aqua", "Dates", "InteractiveUtils", "Pkg", "Printf", "Test"] +test = ["Aqua", "Dates", "InteractiveUtils", "ParallelTestRunner", "Pkg", "Printf", "Test"] diff --git a/test/runtests.jl b/test/runtests.jl index b8bcdbc7..be548fff 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,71 +1,32 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license + using Test, LinearAlgebra, SparseArrays include("util/gha.jl") -include("allowscalar.jl") -include("fixed.jl") -include("higherorderfns.jl") -include("sparsematrix_constructors_indexing.jl") -include("sparsematrix_ops.jl") -include("sparsevector.jl") -include("issues.jl") +testfiles = ["allowscalar.jl", "fixed.jl", "higherorderfns.jl", + "sparsematrix_constructors_indexing.jl", "sparsematrix_ops.jl", + "sparsevector.jl", "issues.jl"] if Base.USE_GPL_LIBS - - include("cholmod.jl") - include("umfpack.jl") - include("spqr.jl") - include("linalg.jl") - include("linalg_solvers.jl") - - nt = @static if isdefined(Threads, :maxthreadid) - Threads.maxthreadid() - else - Threads.nthreads() - end - - # 1. If the OS is Windows and we are in GitHub Actions CI, we do NOT run - # the `threads` tests. - # 2. If the OS is Windows and we are NOT in GitHub Actions CI, we DO run - # the `threads` tests. - # - So, just as an example, if the OS is Windows and we are in - # Buildkite CI, we DO run the `threads` tests. - # 3. If the OS is NOT Windows, we DO run the `threads` tests. + append!(testfiles, ["cholmod.jl", "umfpack.jl", "spqr.jl", "linalg.jl", + "linalg_solvers.jl"]) if Sys.iswindows() && is_github_actions_ci() @warn "Skipping `threads` tests on Windows on GitHub Actions CI" - @test_skip false else - @debug "Beginning the `threads` tests..." - - # Test multithreaded execution - @testset "threaded SuiteSparse tests" verbose = true begin - @testset "threads = $nt" begin - include("threads.jl") - end - # test both nthreads==1 and nthreads>1. spawn a process to test whichever - # case we are not running currently. - other_nthreads = nt == 1 ? 4 : 1 - @testset "threads = $other_nthreads" begin - let p, cmd = `$(Base.julia_cmd()) --depwarn=error --startup-file=no threads.jl` - p = run( - pipeline( - setenv( - cmd, - "JULIA_NUM_THREADS" => other_nthreads, - dir=@__DIR__()), - stdout = stdout, - stderr = stderr), - wait = false) - if !success(p) - error("SuiteSparse threads test failed with nthreads == $other_nthreads") - else - @test true # mimic the one @test in threads.jl - end - end - end - end - - @debug "Finished the `threads` tests..." + push!(testfiles, "threads_suite.jl") end end + +# ParallelTestRunner comes from the Pkg.test target; Julia base CI runs this +# file without it and falls back to the serial path. +if Base.find_package("ParallelTestRunner") !== nothing + using ParallelTestRunner + # Auto CPU thread count detection in ParallelTestRunner is bad + push!(ARGS, "--jobs=$(Sys.CPU_THREADS)") + testsuite = Dict{String,Expr}(splitext(f)[1] => :(include($(joinpath(@__DIR__, f)))) + for f in testfiles) + runtests(SparseArrays, ARGS; testsuite) +else + foreach(include, testfiles) +end diff --git a/test/threads_suite.jl b/test/threads_suite.jl new file mode 100644 index 00000000..5d2d3424 --- /dev/null +++ b/test/threads_suite.jl @@ -0,0 +1,36 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +using Test, SparseArrays + +nt = @static if isdefined(Threads, :maxthreadid) + Threads.maxthreadid() +else + Threads.nthreads() +end + +@testset "threaded SuiteSparse tests" verbose = true begin + @testset "threads = $nt" begin + include("threads.jl") + end + # test both nthreads==1 and nthreads>1. spawn a process to test whichever + # case we are not running currently. + other_nthreads = nt == 1 ? 4 : 1 + @testset "threads = $other_nthreads" begin + let p, cmd = `$(Base.julia_cmd()) --depwarn=error --startup-file=no threads.jl` + p = run( + pipeline( + setenv( + cmd, + "JULIA_NUM_THREADS" => other_nthreads, + dir=@__DIR__()), + stdout = stdout, + stderr = stderr), + wait = false) + if !success(p) + error("SuiteSparse threads test failed with nthreads == $other_nthreads") + else + @test true # mimic the one @test in threads.jl + end + end + end +end From d27f7f4150bea6bb021bf989269b3cf509f7c2c1 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 23 Jul 2026 13:27:30 +0200 Subject: [PATCH 4/4] Comment out forced GC.gc() calls in test_getindex_algs (#740) Co-authored-by: Claude Fable 5 --- test/sparsematrix_constructors_indexing.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/sparsematrix_constructors_indexing.jl b/test/sparsematrix_constructors_indexing.jl index a0396f40..bc97caca 100644 --- a/test/sparsematrix_constructors_indexing.jl +++ b/test/sparsematrix_constructors_indexing.jl @@ -834,7 +834,9 @@ end times = Float64[0,0,0] best = [typemax(Float64), 0] for searchtype in [0, 1, 2] - GC.gc() + # stabilizes the debug timings below, but forces 180 full + # collections across these loops which dominates the file's GC time + # GC.gc() tres = @timed test_getindex_algs(S, I, J, searchtype) res[searchtype+1] = tres[1] times[searchtype+1] = tres[2] @@ -890,9 +892,9 @@ end for I in IA Isorted = sort(I) for S in SA - GC.gc() + # GC.gc() # see comment above ru = @timed S[I, J] - GC.gc() + # GC.gc() rs = @timed S[Isorted, Jsorted] if debug @printf(" %7d | %7d | %7d | %4.2e | %4.2e | %4.2e | %4.2e |\n", round(Int,nnz(S)/size(S, 2)), length(I), length(J), rs[2], ru[2], rs[3], ru[3])