Load a dependency only when calling a method that needs it

I’m building a package for which I want to minimize using load time. It has a bunch of dependencies that are only needed for some specific functionalities, called via specific methods. Can I somehow delay loading the dependencies until the user calls the methods that use them? What is the recommended approach to such a problem?

Note: as I understand it, this is kind of the conjugate of the problem that Requires.jl solves (defining some methods only after the user loads a package).

You can put using in a function like this:

function load_dep()
    @eval using Dependency
end

But this works only if you call this function from global scope, if you call it inside another function, you will not get this dependency in the calling function due to world age.

1 Like

Put those methods in different packages with the relevant dependencies. But not that it may not save a lot of load time in any case.

Also, is load time a bottleneck for you on 1.5/master? For most people, compilation time is more significant.

3 Likes

You can use @eval Base.__toplevel__ import $pkg for loading and Base.invokelatest(<function>, <args>) for actual using. This is how it is done in UrlDownload.jl: https://github.com/Arkoniak/UrlDownload.jl/blob/master/src/UrlDownload.jl#L117-L138 and this implementation was taken from FileIO.jl

I am not sure, but I think that invokelatest can be rather slow compared to a normal function call.

1 Like

Hey Tamas, yes, I’m usually developing on 1.5 and the package is already at 2 sec load time, and growing. I just tried on master and… 0.7 sec. What!!?

I guess I shouldn’t worry so much about dependencies going forward :smiley:

3 Likes

The reduction in the load time you observed in master may be an effect of the work being done to reduce invalidations.

4 Likes

Yeah, I know, I’ve been following that closely with much interest. It’s amazing. I just never thought to measure its effect on my work :slight_smile:

1 Like