JuliaRobotics / RoMEPlotting.jl

2D plotting functionality for the RoME.jl package
MIT License
2 stars 8 forks source link

Loading a RoMEPlotting sysimage fails #140

Open lemauee opened 3 years ago

lemauee commented 3 years ago

Hi,

To reduce the time Julia needs to load RoMEPlotting I created a system image using PackageCompiler.jl

using PackageCompiler
create_sysimage(:RoMEPlotting; sysimage_path="sysimageRoMEPlotting.so")

This works fine, but trying to use it with

julia -J sysimageRoMEPlotting.so

produces an error

fatal: error thrown and no exception handler available.
#<null>
jl_errorf at /buildworker/worker/package_linux64/build/src/rtutils.c:77
jl_load_dynamic_library at /buildworker/worker/package_linux64/build/src/dlload.c:233
#dlopen#3 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Libdl/src/Libdl.jl:109
dlopen at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Libdl/src/Libdl.jl:109
unknown function (ip: 0x7fa984cc147b)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2214 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2398
macro expansion at /home/leopold/.julia/packages/JLLWrappers/KuIwt/src/products/library_generators.jl:61 [inlined]
__init__ at /home/leopold/.julia/packages/HarfBuzz_jll/OFN8Y/src/wrappers/x86_64-linux-gnu.jl:25
jfptr___init___53528 at /home/leopold/Nextcloud/Studium/Masterarbeit/svn/julia/mmiSAM/tools/sysimageRoMEPlotting.so (unknown line)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2214 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2398
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1690 [inlined]
jl_module_run_initializer at /buildworker/worker/package_linux64/build/src/toplevel.c:74
_julia_init at /buildworker/worker/package_linux64/build/src/init.c:779
unknown function (ip: 0x401527)
__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
unknown function (ip: 0x4015d4)

Doing the same procedure with RoME itself works fine. Is there any experience with creating a RoMEPlotting sysimage?

dehann commented 3 years ago

Not with RoMEPlotting unfortunately, but we are using Gadfly for plotting which should work with PackageCompiler.jl. Sure you did see this before from their docs? https://gadflyjl.org/stable/#Compilation-1

My suggestion is perhaps best to get Gadfly.jl working on its own. Or, at least adjacent to the RoME sysimage, and that way only RoMEPlotting.jl will need to be compiled live. https://juliarobotics.org/Caesar.jl/latest/installation_environment/#Ahead-Of-Time-Compile-RoME.so

If both RoME and Gadfly can compile into an image, my expectation is that one image with both should not be too difficult. I'm assuming you are on Linux with Julia 1.5?(followed link to 478 for info after writing)

__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6

lemauee commented 3 years ago

I already put ´RoME,Gadfly,GraphPlot,DistributedFactorGraphs,Compose,ArgParse´ sucessfully into one image, which reduced startup times a lot. I can live with it now, but maybe adding something like a test for this would be nice, so we know if Package Compiler can handle it one day :)

lemauee commented 3 years ago

As @dehann requested, this is the code I currently use to build sysimage for swift startup:

Firstly, I have a include.jl which contains every package I use in my main evaluation script:

using RoME,RoMEPlotting,Gadfly,GraphPlot,DistributedFactorGraphs,Compose,ArgParse

Secondly, theres this (kind of hacky) script taking the include.jl and building a sysimage from it:

using PackageCompiler
pkgString = open(f->read(f, String), "include.jl")
pkgString = replace(pkgString,"using " => "")
pkgString = replace(pkgString,"\n" => "")
pkgString = replace(pkgString,"RoMEPlotting," => "") # fix because starting with it fails ...
pkgNames = split(pkgString,',')
pkgSyms = Symbol.(pkgNames)
create_sysimage(pkgSyms; sysimage_path="$(homedir())/.julia/sysimage_RoME.so")

This state could be put into one file as follows I think:

using PackageCompiler
pkgSyms = [:RoME,:Gadfly,:GraphPlot,:DistributedFactorGraphs,:Compose,:ArgParse]
create_sysimage(pkgSyms; sysimage_path="$(homedir())/.julia/sysimage_RoME.so")

Besides, I'm not not really sure all Packages need to be included like this individually, but it did not hurt things. Whats also still missing are precompile triggers and maybe the directory and project stuff present in https://github.com/JuliaRobotics/RoME.jl/blob/master/compileRoME/compileRoMESysimage.jl . Adding the cd and project stuff should be no problem, but for the precompile triggers and the stuff that should actually be required, I'd need your advice @dehann @Affie . I'd happily file a PR afterwards :)

Affie commented 3 years ago

Hi, you can get some more information here: https://julialang.github.io/PackageCompiler.jl/dev/sysimages/#tracing-1 The easiest way is to just run the test as in the compileRoME example.

dehann commented 3 years ago

Hi Leo,

I'm not not really sure all Packages need to be included like this individually, but it did not hurt things.

Agree, that sounds fine to me too.

for the precompile triggers and the stuff that should actually be required, I'd need your advice

Perhaps easiest is just a draft PR with new files at RoME/compileRoME/<UsecasePlotting>/*.jl on how you are using it (even if not 100% functional). From there we can work towards a better default compile structure. Ultimately the triggers should map to what users are actually using. That balances maintenance load with a useful binary image. It sounds like what we have in compileRoME is an okay starting point but still requires you to add and tweak stuff before your situation is ready to go.

tracing

We can use something like RoME.warmupJIT() or different trigger files for different use cases. Currently it is only the RoME tests. I think perhaps a cool long term approach would be something like:

julia -O3 -e 'using PackageCompiler, Caesar, RoMEPlotting; compileCaesar_so(usecase=:full);'

Not only faster loading times in Julia, but one could then bind on the resulting .so / [.h] from either C++, Python, or otherwise (just using made up names):

#include "include/libcaesar.h"

Best, Dehann

lemauee commented 3 years ago

Hi,

I just sent out the draft PR for you to have a look at. A lot of the test scripts i wanted to use as precompile triggers dont run at the moment, It would be nice to know if thats also the case on your machines.

What I questioned from the beginning on the existing scripts is if its good to keep seperate Project.toml's for the compile script. Is there a deeper reason you did this for the initial RoME-Compile-script @Affie ? (Besides that for compiling RoMEPlotting we obviosly also need this in that file)

Also testing the compilation in CI would be a great thing, compiling and booting up julia with it.

Another question is the storage location of the output file. I always found it nice to store this directly in my ~/.julia directory or some subfolder to make it easy to find and start julia with it. But this may be personal preference.

Best, Leo

KristofferC commented 3 years ago

Might be fixed? https://github.com/JuliaLang/PackageCompiler.jl/issues/478#issuecomment-811933025