Skip to content

Commit c6732a7

Browse files
Avoid duplicate stat calls during startup/loading (#55331)
Avoids immediately successive stat calls for the same path during startup & loading. According to MacOS Instruments this reduces `stat64` calls during `--start=no -e "using Pkg"` from 844 to 672. On MacOS I don't see a speed improvement, but on WSL2 @timholy reported the test from #55171 sees a modest improvement. This PR (10 iterations) ``` tim@diva:~/.julia/bin$ time for i in {1..10}; do ./cli --help &> /dev/null; done real 0m2.999s user 0m3.547s sys 0m6.552s ``` master ``` real 0m3.217s user 0m3.794s sys 0m6.700s ``` 1.11-rc2: ``` real 0m3.746s user 0m4.169s sys 0m6.755s ``` I left the `@debug`s in as they might be useful for similar investigations.
1 parent 19165be commit c6732a7

File tree

3 files changed

+17
-7
lines changed

3 files changed

+17
-7
lines changed

base/client.jl

+2
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,13 @@ function _global_julia_startup_file()
339339
# If it is not found, then continue on to the relative path based on Sys.BINDIR
340340
BINDIR = Sys.BINDIR
341341
SYSCONFDIR = Base.SYSCONFDIR
342+
p1 = nothing
342343
if !isempty(SYSCONFDIR)
343344
p1 = abspath(BINDIR, SYSCONFDIR, "julia", "startup.jl")
344345
isfile(p1) && return p1
345346
end
346347
p2 = abspath(BINDIR, "..", "etc", "julia", "startup.jl")
348+
p1 == p2 && return nothing # don't check the same path twice
347349
isfile(p2) && return p2
348350
return nothing
349351
end

base/loading.jl

+7-5
Original file line numberDiff line numberDiff line change
@@ -822,14 +822,15 @@ end
822822
# given a project directory (implicit env from LOAD_PATH) and a name,
823823
# find an entry point for `name`, and see if it has an associated project file
824824
function entry_point_and_project_file(dir::String, name::String)::Union{Tuple{Nothing,Nothing},Tuple{String,Nothing},Tuple{String,String}}
825-
path = normpath(joinpath(dir, "$name.jl"))
826-
isfile_casesensitive(path) && return path, nothing
827825
dir_name = joinpath(dir, name)
828826
path, project_file = entry_point_and_project_file_inside(dir_name, name)
829827
path === nothing || return path, project_file
830828
dir_jl = dir_name * ".jl"
831829
path, project_file = entry_point_and_project_file_inside(dir_jl, name)
832830
path === nothing || return path, project_file
831+
# check for less likely case with a bare file and no src directory last to minimize stat calls
832+
path = normpath(joinpath(dir, "$name.jl"))
833+
isfile_casesensitive(path) && return path, nothing
833834
return nothing, nothing
834835
end
835836

@@ -3809,7 +3810,7 @@ end
38093810
end
38103811
if !ispath(f)
38113812
_f = fixup_stdlib_path(f)
3812-
if isfile(_f) && startswith(_f, Sys.STDLIB)
3813+
if _f != f && isfile(_f) && startswith(_f, Sys.STDLIB)
38133814
continue
38143815
end
38153816
@debug "Rejecting stale cache file $cachefile because file $f does not exist"
@@ -3831,13 +3832,14 @@ end
38313832
return true
38323833
end
38333834
else
3834-
fsize = filesize(f)
3835+
fstat = stat(f)
3836+
fsize = filesize(fstat)
38353837
if fsize != fsize_req
38363838
@debug "Rejecting stale cache file $cachefile because file size of $f has changed (file size $fsize, before $fsize_req)"
38373839
record_reason(reasons, "include_dependency fsize change")
38383840
return true
38393841
end
3840-
hash = isdir(f) ? _crc32c(join(readdir(f))) : open(_crc32c, f, "r")
3842+
hash = isdir(fstat) ? _crc32c(join(readdir(f))) : open(_crc32c, f, "r")
38413843
if hash != hash_req
38423844
@debug "Rejecting stale cache file $cachefile because hash of $f has changed (hash $hash, before $hash_req)"
38433845
record_reason(reasons, "include_dependency fhash change")

base/stat.jl

+8-2
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,14 @@ macro stat_call(sym, arg1type, arg)
184184
end
185185

186186
stat(fd::OS_HANDLE) = @stat_call jl_fstat OS_HANDLE fd
187-
stat(path::AbstractString) = @stat_call jl_stat Cstring path
188-
lstat(path::AbstractString) = @stat_call jl_lstat Cstring path
187+
function stat(path::AbstractString)
188+
# @info "stat($(repr(path)))" exception=(ErrorException("Fake error for backtrace printing"),stacktrace())
189+
@stat_call jl_stat Cstring path
190+
end
191+
function lstat(path::AbstractString)
192+
# @info "lstat($(repr(path)))" exception=(ErrorException("Fake error for backtrace printing"),stacktrace())
193+
@stat_call jl_lstat Cstring path
194+
end
189195
if RawFD !== OS_HANDLE
190196
global stat(fd::RawFD) = stat(Libc._get_osfhandle(fd))
191197
end

0 commit comments

Comments
 (0)