Skip to content

Commit

Permalink
Fix algorithmic complexity of cycle detection
Browse files Browse the repository at this point in the history
The circular dependency detection in `precompile` has poor algorithmic
complexity. In a project with deep and broad dependency trees of hundreds
of packages, this introduces a significant delay before the start of
precompilation work. Fix that by switching the cycle detection to a
simple open-coded DFS walk.
  • Loading branch information
Keno committed Oct 12, 2023
1 parent 894cc3f commit a96a9c3
Showing 1 changed file with 20 additions and 6 deletions.
26 changes: 20 additions & 6 deletions src/API.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1208,13 +1208,27 @@ function precompile(ctx::Context, pkgs::Vector{PackageSpec}; internal_call::Bool

# find and guard against circular deps
circular_deps = Base.PkgId[]
function in_deps(_pkgs, deps, dmap)
isempty(deps) && return false
!isempty(intersect(_pkgs, deps)) && return true
return any(dep->in_deps(vcat(_pkgs, dep), dmap[dep], dmap), deps)
depths = Dict{Base.PkgId, Int}(pkg => 0 for pkg in keys(depsmap))
function dfs_scan!(pkg, dmap, depth=0)
for dep in dmap[pkg]
already_visited = true
depdepth = get!(depths, dep) do
already_visited = false
depth + 1
end
# Will be visited at top level
depdepth == 0 && continue
if depdepth < depth+1
# Found cycle
return true
elseif !already_visited
dfs_scan!(dep, dmap, depth+1) && return true
end
end
return false
end
for (pkg, deps) in depsmap
if in_deps([pkg], deps, depsmap)
for pkg in keys(depsmap)
if dfs_scan!(pkg, depsmap)
push!(circular_deps, pkg)
notify(was_processed[pkg])
end
Expand Down

0 comments on commit a96a9c3

Please sign in to comment.