Skip to content

Commit

Permalink
Isolate string interpolation in error paths for sparse matrix constru…
Browse files Browse the repository at this point in the history
…ctors (JuliaLang#38446)

This provides a better-than-3x speed improvement for `spzeros(5, 5)`:

julia> @Btime spzeros(5, 5);
  341.371 ns (3 allocations: 288 bytes)

julia> Revise.track(SparseArrays)

julia> @Btime spzeros(5, 5);
  103.633 ns (3 allocations: 288 bytes)
  • Loading branch information
timholy committed Nov 25, 2020
1 parent a7168a5 commit 4b739e7
Showing 1 changed file with 12 additions and 5 deletions.
17 changes: 12 additions & 5 deletions stdlib/SparseArrays/src/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,29 @@ function sparse_check_Ti(m::Integer, n::Integer, Ti::Type)
end

function sparse_check(n::Integer, colptr::Vector{Ti}, rowval, nzval) where Ti
# String interpolation is a performance bottleneck when it's part of the same function,
# ensure we only do it once committed to the error.
throwstart(ckp) = throw(ArgumentError("$ckp == colptr[1] != 1"))
throwmonotonic(ckp, ck, k) = throw(ArgumentError("$ckp == colptr[$(k-1)] > colptr[$k] == $ck"))

sparse_check_length("colptr", colptr, n+1, String) # don't check upper bound
ckp = Ti(1)
ckp == colptr[1] || throw(ArgumentError("$ckp == colptr[1] != 1"))
ckp == colptr[1] || throwstart(ckp)
@inbounds for k = 2:n+1
ck = colptr[k]
ckp <= ck || throw(ArgumentError("$ckp == colptr[$(k-1)] > colptr[$k] == $ck"))
ckp <= ck || throwmonotonic(ckp, ck, k)
ckp = ck
end
sparse_check_length("rowval", rowval, ckp-1, Ti)
sparse_check_length("nzval", nzval, 0, Ti) # we allow empty nzval !!!
end
function sparse_check_length(rowstr, rowval, minlen, Ti)
throwmin(len, minlen, rowstr) = throw(ArgumentError("$len == length($rowstr) < $minlen"))
throwmax(len, max, rowstr) = throw(ArgumentError("$len == length($rowstr) >= $max"))

len = length(rowval)
len >= minlen || throw(ArgumentError("$len == length($rowstr) < $minlen"))
!isbitstype(Ti) || len < typemax(Ti) ||
throw(ArgumentError("$len == length($rowstr) >= $(typemax(Ti))"))
len >= minlen || throwmin(len, minlen, rowstr)
!isbitstype(Ti) || len < typemax(Ti) || throwmax(len, typemax(Ti), rowstr)
end

size(S::SparseMatrixCSC) = (getfield(S, :m), getfield(S, :n))
Expand Down

0 comments on commit 4b739e7

Please sign in to comment.