Skip to content
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

Pre-compile Code With Endless Loop Or Tasks #446

Closed
yoh-meyers opened this issue Sep 23, 2020 · 10 comments
Closed

Pre-compile Code With Endless Loop Or Tasks #446

yoh-meyers opened this issue Sep 23, 2020 · 10 comments

Comments

@yoh-meyers
Copy link

yoh-meyers commented Sep 23, 2020

Hello,

Firstly thank you for creating this useful package.

My issue is that I would like to pre-compile code with an endless loop.
More specifically for web applications, one would have to continuously be listening to incoming connections.
That said, I did see https://discourse.julialang.org/t/packagecompiler-sockets-web-app/28793/11 .

However I do think it is a necessary feature for devops.
As otherwise each time one pushes updates to Docker/Kubernetes, the newly compiled image returns 502 HTTP errors for 10 mins, time that Julia is compiling all code.
And first requests to all web endpoints take more time to load.
This of course is not acceptable for a production web app.

I would definitely like to pro-actively help to implement this new feature.
May I request a bit more guidance on where in code base necessary changes would need to be made, to support this.

Thanks

@yoh-meyers yoh-meyers changed the title Pre-compile Code WIth Endless Loop Or Tasks Pre-compile Code With Endless Loop Or Tasks Sep 23, 2020
@fredrikekre
Copy link
Member

Can't you just 1. start the server, 2. create some representative requests, 3. shut down in the precompile script?

@yoh-meyers
Copy link
Author

Yes that is possible, though quite a workaround as the number of endpoints would increase.

Am suggesting above from perspective of making Julia easier to use.

I do make use of Pkg.precompile, though as code is not saved (JuliaLang/julia#30488), the web app is still unresponsive when initially started.

@fredrikekre
Copy link
Member

Yes that is possible, though quite a workaround as the number of endpoints would increase.

Perhaps I misunderstand the issue then, but how do you expect Julia to compile code for the endpoints that your compile script does not exercise? If you do that correctly there should be no overhead once you start the application.

@yoh-meyers
Copy link
Author

Yes makes sense that all functions behind endpoints would need to be called, before starting application.
So yes your suggestion makes sense.

Thanks

@yoh-meyers
Copy link
Author

I have implemented suggested solution, but due to HTTP.jl socket, I still get UndefVarError: uv_jl_connectioncb not defined error.
This even though I do terminate the process after starting the server in the compile script.

So my question is what changes could I add to PackageCompiler.jl, to avoid this behaviour?
If I understand tasks cannot be serialised, but was curious if there was a fix I could add.

@yoh-meyers yoh-meyers reopened this Sep 23, 2020
@KristofferC
Copy link
Member

The link you posted is for a very old package compiler. Post the script that you currently use to create the sysimage.

@yoh-meyers
Copy link
Author

I am converting https://github.com/DanceJL/Dance.jl/blob/master/files/dance.jl to a compile script.

So my script is:

Base.reinit_stdio()
Base.init_depot_path()
Base.init_load_path()

import Pkg
Pkg.activate(".")

Settings = []


#=
    Multi-processing case.
    Requires Distributed to be installed.
    - Uncomment below, specifying number of desired processes (default is number of system cores)
    - Comment `import Dance` below
=#
#= using Distributed
addprocs(length(Sys.cpu_info()))
@everywhere import Dance =#
import Dance


#=
    STEP 1
    If apart from `static_dir` as defined in `routes.jl` there are dirs to ignore adding to LOAD_PATH
        => add to `ignore_dirs`
    By default all other sub-dirs of project structure will be added
=#
ignore_dirs = ["_unused", "html", "imports", "quasar", "settings"]
if Dance.populate_settings(abspath(@__DIR__))
    global Settings
    Settings = Dance.Configuration.Settings
    for item in Dance.populate_load_path(abspath(@__DIR__); ignore_dirs=ignore_dirs)
        push!(LOAD_PATH, item)
    end
end


#=
    STEP 2
    Import modules here below, not above
    (STEP 1 populated `LOAD_PATH`)
=#
import Importer

function main(args)
    if Dance.populate_router(abspath(@__DIR__))
        include(Settings[:routes_filename]*".jl")

        ## STEP 3: Add custom scripts here that need be run before launching Dance ##
        if length(args)>0
            if "new" in args
                Importer.fetch_new_data()
            elseif "pre" in args
                Importer.pre_fetch_new_data()
            end
        end
        ##############################################

        start_server::Bool = true
        if length(args)>0
            if "repl" in args
                start_server = false
            end
        end

        Dance.launch(start_server)

        sleep(10)
        run(`PID=$!`)
        run(`kill $PID`)
    end
end


main(ARGS)

empty!(LOAD_PATH)
empty!(DEPOT_PATH)

@yoh-meyers
Copy link
Author

The Dance.launch part calls:

HTTP.Handlers.serve(server_host, server_port) do request::HTTP.Request
    render(;request_headers=request.headers, request_method=request.method, request_path=request.target, request_payload=String(take!(IOBuffer(request.body))))
end

which is the loop

@KristofferC
Copy link
Member

This is not how you use PackageCompiler. See https://julialang.github.io/PackageCompiler.jl/dev/sysimages/

@yoh-meyers
Copy link
Author

Ok understand that I need to change structure of code to match that of standard package.
Was following https://julialang.github.io/PackageCompiler.jl/dev/devdocs/binaries_part_2/#Interacting-with-Julia-through-libjulia.-1 and thought above was possible.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants