It seems to me that it might make sense to have a package consist of multiple (dozens?) related files that the user does not necessarily need all at once. What is the standard mechanism for dealing with this? (Is there one?)
So, let’s say the package is called P1. There is a P1.jl file (top-level), but then there are let’s say three other files. When as a user I want to use some function I may need one of these three. Presumably there is a module in that file. How do I load that module for import? Do I have to use Pkg.dir()?
Specifying what is getting loaded up front allows for precompilation. This will likely be a much larger performance increase than trying to “hot load” new code. For example, DataFrames loads ~10x faster with precompilation than without.
So are you saying that no matter how big the package gets pre-compilation will take care of the load time?
Isn’t there a price that one has to pay in terms of the resources consumed that are involved in loading a huge package?
Yes, indeed. But at the same time I want to keep the relationship of the “sub”-packages intact. Right now I have the package split up into dozens of modules. These however get all loaded at the same time whenever I say using MyPackage, whether I need them or not.
So really what I’m looking for is some way of having multiple packages under the umbrella of one top package. Does anyone know if there is a beast like this around already?
Julia is JIT compiled and the cost of compiling functions is typically much larger than just “loading” the code. It is unlikely that you will beat the 10-50x performance boost of precompilation, while keeping the same functionality.
Your package GitHub - PetrKryslUCSD/FinEtools.jl: Finite Element tools in Julia is currently running with precompilation off. Enabling it makes load time go from 5 seconds to 0.08 seconds. What part of those 0.08 seconds are you trying to improve and do you think it is relevant comparing to other things like compilation time when functions are actually called?
then you can do using stuff without it loading the here module. Then if you need to load that too, you can execute using stuff.here and then that will be loaded. Is that what you are want?
Maybe I’m not understanding, but this is what I get:
julia> module stuff
module here
export x
x = 1
end
end
stuff
julia> using stuff
julia> stuff.
eval here
julia> stuff.here
stuff.here
julia> stuff.here.x
1
I. e. no need to do using stuff.here. It is already there when I do using stuff.
julia> module stuff
module here
export x
x = 1
end
end
stuff
julia> using stuff
julia> x
ERROR: UndefVarError: x not defined
Stacktrace:
[1] macro expansion at ./REPL.jl:97 [inlined]
[2] (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:73
julia> using stuff.here
julia> x
1
So you have to call using stuff.here in order for the here module to be loaded into main.
Of course, you can always do stuff.here.x no matter what, but that is independent of using.
Oh okay, well if you want to have code in your package that doesn’t get loaded, then you will have to just simply include it in a separate file like src/extra.jl. Then you would have to do cd(Pkg.dir("Name")) and then include("src/extra.jl") to load that code.
However, you’re probably better off using precompile.
That is a good point. However my package has around five thousand lines, give or take. What if I managed to rewrite Nastran with its five million lines of code? Are we then talking about eighty seconds to load the package?
Another thing you could do is put your extra module ExtraModule into mod/ExtraModule.jl and then in your main module PkgName.jl script add a line like this
Pkg.dir is not ideal to use like this because it will fail if the package is installed somewhere else than Pkg.dir. Use relative includes instead like joinpath(@__DIR__, "..", "mod").
Also, relying on user controlled global behavior like LOAD_PATH is quite fragile and possibly confusing for users.
True, at that point it probably just makes sense to split it into multiple separate packages anyway, since you’d have to worry about ExtraModule possibly conflicting with another package name, the way it is used at that point is essentially as if it is another package anyway.