-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Switch to using const
Ref
instead of mutable global
#829
Comments
But what about code that accesses At the very least, I think there should be strict benchmarks that conclusively prove there is something to be gained here. E.g. similar to what I did in PR #812. |
Updating packages to use |
Which is not going to be an easy task as we use the upstream version |
Maybe we can use
|
So I tried to see what benefit this brings, if any, by using the same setup as in PR #812, and tested First, I set up a fresh Julia depot with just that JLL (and its dependencies in it), and then took a fresh baseline timing (see the end of this comment for the results). Then I modified all those JLLs to imitate the changes proposed here (as I understand them), limited to all the
This results in diffs like this (let me know if that correctly captures the gist of the idea proposed here): diff --git a/Zlib_jll/hR4qW/src/wrappers/aarch64-linux-gnu.jl b/Zlib_jll/hR4qW/src/wrappers/aarch64-linux-gnu.jl
index e9b35b6..127a3ed 100644
--- a/Zlib_jll/hR4qW/src/wrappers/aarch64-linux-gnu.jl
+++ b/Zlib_jll/hR4qW/src/wrappers/aarch64-linux-gnu.jl
@@ -11,7 +11,7 @@ LIBPATH_default = ""
const libz_splitpath = ["lib", "libz.so"]
# This will be filled out by __init__() for all products, as it must be done at runtime
-libz_path = ""
+const libz_path = Ref{String}()
# libz-specific global declaration
# This will be filled out by __init__()
@@ -29,12 +29,12 @@ function __init__()
# Initialize PATH and LIBPATH environment variable listings
global PATH_list, LIBPATH_list
- global libz_path = normpath(joinpath(artifact_dir, libz_splitpath...))
+ global libz_path[] = normpath(joinpath(artifact_dir, libz_splitpath...))
# Manually `dlopen()` this right now so that future invocations
# of `ccall` with its `SONAME` will find this path immediately.
- global libz_handle = dlopen(libz_path)
- push!(LIBPATH_list, dirname(libz_path))
+ global libz_handle = dlopen(libz_path[])
+ push!(LIBPATH_list, dirname(libz_path[]))
# Filter out duplicate and empty entries in our PATH and LIBPATH entries
filter!(!isempty, unique!(PATH_list)) Now to the timings. First, the baseline (with default optimization level / -O1 / -O0; note that just the Julia startup is 90-95 ms, as in PR #812, so that should be subtracted from all numbers below)
Now the results with the change proposed here:
Conclusion: Things get faster! Albeit just in the order of 1-2%. |
Yes, I also got only small speedup, but something is better than nothing... and at least here no downside. I wasn't really expecting a big speedup, as you're not compiling a lot of code, given binaries... but note this adds up. I was looking into FFMPEG also myself, and all dependencies, and thereof etc. need the same treatment for same speedup. I would want/propose something doing it for all JLL packages... |
But there is a downside: this introduces an incompatibility, code which accesses |
Maybe I or you misunderstand. The change I made (if applied to a JLL package) works on 1.5+ but also on older. It just doesn't have any effect on older. Also, as is, you need to opt into this for a JLL package, by releasing a new version. Your old version still works, and packages depending on it. And if you upgrade the minimum requirements to the newer then should be ok, as I explained. You can wait with doing that if you do not trust me. |
If the type of, say, Of course nothing may be directly accessing |
We just need to use julia> cacert_ref = Ref{String}("foo")
Base.RefValue{String}("foo")
julia> Base.@deprecate_binding cacert cacert_ref[] false
julia> cacert
WARNING: Main.cacert is deprecated, use cacert_ref[] instead.
likely near REPL[7]:1
"foo" |
We're going to be changing everything to be functions in the near future, once So we're going to have a breaking release of JLL packages soon anyway. Our plan is to by default provide the old bindings on Julia < 1.6, and provide the new, faster and more feature-complete bindings on Julia >= 1.6. We're going to try and come up with a good way for packages to tell JLL packages that they want to opt-out of the fast bindings and still use slow bindings (for package authors that want to support Julia 1.3-1.6 with one codebase, for instance), possibly using In summary, your ccall((:fooify, libfoo), ...) to: ccall((:fooify, libfoo()), ...) your
to: open(foo_conf(), "r") do
...
end I haven't 100% finalized this yet, but I'm pretty sure we're going to change fooifier() do fooifier_path
run(`$(fooifier_path) ...`)
end You'll instead just do: run(`$(fooifier()) ...`) But this will require another fix to Julia such that environment blocks properly merge their |
I believe this issue has been addressed now with the new JLLs that are based on JLLWrappers.jl. |
Not entirely since there are still some mutable globals, but if the main concern of this ticket was performance, this has been largely addressed by JLLWrappers, yes. |
I noticed in https://github.com/JuliaBinaryWrappers/MozillaCACerts_jll.jl/blob/12060f50fe9948363c300167506f26aa6c75415d/src/wrappers/any.jl#L18 that
cacert
is a mutable global. It seems like it would be more performant to change the code to be:I'm guessing the rational for using a mutable global is purely for convenience.
The text was updated successfully, but these errors were encountered: