Help to reduce very long compilation time

Hi!

I am building a package to create text user interfaces in Julia using ncurses: TextUserInterfaces.jl

Now, I am facing a very, very slow compilation time. For example, the following code just initialize NCurses, create a window with a label, and destroys everything:

using TextUserInterfaces

# Create the TUI.
function test()
    # Initialize the TUI.
    init_tui("/usr/local/Cellar/ncurses/6.1/lib")
    NCurses.noecho()

    win = create_window(border = true, title = " WINDOW ",
                        anchor_left = (rootwin, :left, 0),
                        anchor_top = (rootwin, :top, 0),
                        anchor_right = (rootwin, :right, 0),
                        anchor_bottom = (rootwin, :middle, 0))

    create_widget(Val{:label}, win, text = "Top right",
                  anchor_right = (win, :right, 0),
                  anchor_top   = (win, :top,   0))

    refresh_all_windows()
    NCurses.update_panels()
    NCurses.doupdate()

    destroy_tui()
end

test()

Take a look at the difference when I run it for the first and second times:

julia> @time include("teste6.jl")
  1.167181 seconds (3.41 M allocations: 172.807 MiB, 3.10% gc time)

julia> @time include("teste6.jl")
  0.024663 seconds (19.38 k allocations: 890.259 KiB)

For a very complex TUI, with lots of widgets, this time is almost prohibitive (taking more than 5s to show the TUI). Is there anything I can do to debug/reduce it?

EDIT: Just an additional information, putting the function inside a module did not solve the problem.

1 Like

Well, running julia with -O0 --compile=min reduce this A LOT:

julia> @time include("teste6.jl")
  0.377436 seconds (861.08 k allocations: 48.172 MiB, 1.64% gc time)

julia> @time include("teste6.jl")
  0.007598 seconds (2.80 k allocations: 116.903 KiB)

So I guess I am seeing the compile latency. Right?

Unrelated to your question, note that we have Ncurses_jll which provides the library for all platforms.

3 Likes

I had a look on your sources and you are using Integer abstract type a lot. Maybe it would compile faster if you used Int or T<:Integer?

2 Likes

It is amazing! It will solve some problems. However, its seems to have a bug and I cannot load ncurses in macOS:

Thanks for the tip!! It helped to reduce the compilation time, even though it is still high:

# After changing everything to Int
julia> @time include("teste6.jl")
  0.976859 seconds (3.18 M allocations: 159.402 MiB, 3.28% gc time)

After your tips, TextUserInterfaces.jl is playing really nice with Ncurses_jll.jl! Since I do not have a windows machine to test, can you please tell me if there is any change to make Ncurses_jll works on Windows?

Moreover, Ncurses_jll.jl is working perfectly when building a compiled TUI using PackageCompiler.jl. In this case, all that compilation time is gone and the interface is opened very fast.

My only question is: with this setup, if ~/.julia is not present, then the artifacts related to Ncurses are downloaded. Is there a way to bundle those artifacts together with the other libraries to avoid this download?

:tada:

No idea, I don’t use Windows either :slightly_smiling_face: What’s the problem?

I’m not sure what you want to achieve, could you please elaborate?

I have never been able to run Ncurses in Windows. If you said it is working, then I would create a partition here with Window to test :slight_smile:

The ultimate idea of TextUserInterfaces.jl is to ship compiled TUIs to accomplish some tasks. In this case, it will be nice if everything is bundled in one single folder without requiring internet access. I can, of course, manually copy ncurses libraries to the directory created by PackageCompiler.jl. I am just wondering if there is an easier way.

I usually just test binary packages for macOS and Windows with Travis or AppVeyor and see what happens. I only use GNU/Linux on my machine, that’s the only system I have direct access to.

Not really, because the binaries are different for each of the 13 (and counting) currently supported platforms. Unless you’re going to package 13 different versions of your project, that doesn’t help much.

1 Like

That is exactly the point of the create_app function in PackageCompilerX (https://kristofferc.github.io/PackageCompilerX.jl/dev/apps/). It you use the artifact system, it will automatically copy all artifacts and set up depot directory etc so you can just ship the whole thing to another machine.

You can see an example at https://github.com/Gnimuc/Redux.jl/tree/master/examples/App which uses CImGu.jl.

7 Likes

Thanks!! I really did not know anything about the PackageCompilerX.jl until now. It seems very good.