-
Notifications
You must be signed in to change notification settings - Fork 37
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
Initialize pointers at runtime #93
Conversation
Thanks for the help! I agree that the way in which ENV variables interact with precompilation is weird. My last commit worked on unix, but how things work for Windows remains unclear to me. I've tried all kinds of tricks to inspect Julia's ENV at the time of the failing ccalls to libwand, and I went as far as to build an internal precompiled |
Ok yeah it's probably an issue with precompilation the ENV vars. Not sure if we can do anything about the load time .... |
What about once again writing any "system" constants (paths etc.) to a file in |
yeah the paths are basically already determined and fixed. But the more time conusming part is loading all the symbols in particular MagickWandGenesis and some of the other symbols too. BTW I think there is a problem in the finalizers in this package (I don't know how to debug finalizers and all the reference counts) one thing we are not doing is calling It's kinda hard for me to figure out all these things since I can't find a good clear API reference, the imagemagick website doesn't make it clear... (Do you have any good references on the API ) |
I just realized that this is no slower than master MagickWandGenesis is the dominant cost and both here and on master they are loaded in the init files, loading the pointers of the other symbols in a negligible cost. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps consider the Ref
version of libversion
, but other than that, LGTM.
src/libmagickwand.jl
Outdated
ccall((:MagickWandGenesis, libwand), Void, ()) | ||
|
||
libversion_string = queryoption("LIB_VERSION_NUMBER") | ||
global libversion = VersionNumber(join(split(libversion_string, ',')[1:3], '.')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to use theRef{VersionNumber}
version here? __init__()
isn't called during compilation, but libversion
is used in a precompiled function (https://github.com/musm/ImageMagick.jl/blob/b1178deb283ee2e5ec1e449ddb4b80a7c67e728e/src/ImageMagick.jl#L155).
Yes, we should call I haven't found a better reference than the regular C API docs (https://www.imagemagick.org/script/magick-wand.php), but even there it's clear that the exit procedure should destroy all the wands and then call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merge whenever you two are satisfied. Thanks for tackling a long-standing problem!
src/libmagickwand.jl
Outdated
end | ||
|
||
const libmagic = Ref{Ptr{Void}}() | ||
func(fun::Symbol) = Libdl.dlsym(libmagic[], fun) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this get a more descriptive name?
src/libmagickwand.jl
Outdated
const libmagic = Ref{Ptr{Void}}() | ||
func(fun::Symbol) = Libdl.dlsym(libmagic[], fun) | ||
|
||
const MagickWandGenesis = Ref{Ptr{Void}}() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the julia convention of using uppercase for types & modules, is it worth the extra verbosity of calling these libwand_MagickWandGenesis
? I don't feel strongly about this, but thought I'd at least bring it up.
With regards to cleanup: what about having julia> A = rand(5,5)
5×5 Array{Float64,2}:
0.687806 0.218271 0.718677 0.50439 0.974442
0.51159 0.0894912 0.528783 0.468124 0.93002
0.704555 0.0490828 0.43582 0.46748 0.583288
0.739887 0.561882 0.966313 0.188641 0.246377
0.16764 0.665912 0.758272 0.697644 0.0569193
julia> B = rand(5, 5)
5×5 Array{Float64,2}:
0.196685 0.608029 0.168657 0.051015 0.733482
0.186336 0.385804 0.590266 0.48538 0.11401
0.774902 0.113197 0.418957 0.159507 0.887277
0.427635 0.757624 0.623393 0.207146 0.833457
0.126983 0.210338 0.345119 0.894254 0.00865314
julia> w = WeakKeyDict()
WeakKeyDict{Any,Any} with 0 entries
julia> w[A] = nothing
julia> w[B] = nothing
julia> w
WeakKeyDict{Any,Any} with 2 entries:
[0.687806 0.218271 … 0.50439 0.974442; 0.51159 0.0894912 … 0.468124 0.93002; … ; 0.739887 0.561882 … 0.188641 0.246377; 0.16764 0.665912 … 0.697644 0.0569193] => nothing
[0.196685 0.608029 … 0.051015 0.733482; 0.186336 0.385804 … 0.48538 0.11401; … ; 0.427635 0.757624 … 0.207146 0.833457; 0.126983 0.210338 … 0.894254 0.00865314] => nothing
julia> A = []
0-element Array{Any,1}
julia> gc(); gc()
julia> w
WeakKeyDict{Any,Any} with 1 entry:
[0.196685 0.608029 … 0.051015 0.733482; 0.186336 0.385804 … 0.48538 0.11401; … ; 0.427635 0.757624 … 0.207146 0.833457; 0.126983 0.210338 … 0.894254 0.00865314] => nothing
julia> for items in w
@show items
end
items = Pair{Any,Any}([0.196685 0.608029 0.168657 0.051015 0.733482; 0.186336 0.385804 0.590266 0.48538 0.11401; 0.774902 0.113197 0.418957 0.159507 0.887277; 0.427635 0.757624 0.623393 0.207146 0.833457; 0.126983 0.210338 0.345119 0.894254 0.00865314], nothing) |
There is something very odd going on in Windows where ImageMagick is picking up a strange version in the |
@musm I've pushed two commits to your branch that fix the Windows build, including the issues with the reported version. The commit descriptions provide some more info on what I've done. |
@Allardvm Thanks! BTW are you sure we need to add them to the start of the path? It's really confusing why Also I'd like to find a cleaner way of initializing the const init_envs = Dict{String,String}()
# Find the library
const depsfile = joinpath("..", "deps", "deps.jl")
if isfile(depsfile)
include(depsfile)
... and then for (key, value) in init_envs
ENV[key] = value
end is pretty ugly since it's not needed when Can we confirm that the function need to be initialized at runtime? Another strategy is the following: I think the advantage of the current approach is that corresponding function calls are fast. Where as with the strategy in the docs the first call with initialize it and then subsequent calls will be cached. So perhaps the initial package load time will be slightly lower (however I think the dominant cost is initializing |
On my Windows machine, I get the
Everything also works fine on OSX, but the Windows build fails if the binaries aren't in
Yes, that's indeed confusing, and I'm not getting this error on OSX. What do you run to get this error?
I'm 100% with you on this. Too bad it's a bit of a mess to prototype alternatives since Unix and Windows keep tripping over different things. Maybe things will be a bit more consistent now that we load the Windows library the proper way and actually manage to call
I have not yet seen a Windows build pass the tests without this. I'm fine with the current load-time of the library. It's a pretty sizable library and loading is still quite fast. The approach in the docs add further complexity that I'm not sure is worth it for us. |
@Allardvm I pushed a few more commits, primarily changing how we get the library version and also a couple more tests regarding the relative paths and adding to path in windows environments to double check things. |
6d2acbd
to
bac6498
Compare
@Allardvm do you mind squashing some of your commits? BTW I can confirm that appveyor fails if you don't include the Another idea is to perhaps call the symbols within : withenv( ....apropriate env vars...)
....
end not sure if that is cleaner or not |
More consistent fix to support libraries in the system path Readme now uses Homebrew.jl interface to fix borked installations Made fix compatible with precompilation + update libversion on init Avoid global const in __init__
- MagickWandGenesis needs to be included as a Ref for the Windows fix to work - `depsfile` needs a relative path to work regardless of the user’s pwd() - The binaries in the ImageMagick library need to be available in the user’s PATH. The strange “could not find coder X” errors when using the ImageMagick installation with the directories in place aren’t because the coders couldn’t be found, but because they couldn’t be loaded with “convert.exe”—since it wasn’t in the PATH. By binding against ImageMagick in its proper file structure, Windows also loads the correct library (as evidenced by the version number it reports).
I've squashed every single consecutive commit by myself so the log now interleaves between your and my commits :) |
I'm satisfied with the current solution. If this passes the tests, then we can merge this as far as I'm concerned. We should keep a close eye on any issues caused by removing the OSX |
@Allardvm that makes sense. I think there is perhaps some bad interaction between paths in windows (probably with the required packages or pre installed packages on appveyor though either bad bindeps or winrpm configurations that cause the windows builds to fail without the path set) Now that I think about it more carefully perhaps we should just add back the path overloading on osx as well. Do you mind taking care of this? (I am not familiar with the exact path that needs to be added) After this change we can merge this pr |
Good spot on terminate instead of terminus! ImageMagick bin is now in the OSX path, and I've made the ENV's a bit more defensive by pointing it to an |
thank you very much! I think the commits are fine the way they now look! That sounds regarding pointing explicitly to the |
Absolutely to the release. In case you don't know, I think you can do this too (not that I mind doing it): we're using attobot, so it's as easy as going to the "releases" tab on the main page and creating a new one. |
Woot! 🎆 |
@timholy thanks for tagging. Are you sure attobot is installed? I don't see corresponding METADATA entry? It might have to be enabled a per package basis. |
I'm pretty sure we did, at one point. But I just checked, and it was only MsgPack. I kinda suspect it might have gotten reset. I'm going to turn it on for all repos in JuliaIO (and you can complain here if you don't want that). |
That would be much better. Or use an absolute path for the executable, or imagemagick-specific environment variables to tell it where to load everything. Messing with PATH should be done very, very sparingly, especially on windows due to dll conflicts. |
@timholy
@Allardvm this fixes the windows build for me (btw I find it strange that the
ENV
variables have to loaded at runtime)Unfortunately this makes loading ImageMagick slow