Help reducing compilation time

Hi!

I have the following function:

function textview(
    lines::Vector{T},
    view::NTuple{4, Int};
    active_highlight::String = _CSI * "30;43m",
    active_match::Int = 0,
    frozen_columns_at_beginning::Int = 0,
    frozen_lines_at_beginning::Int = 0,
    highlight::String = _CSI * "7m",
    maximum_number_of_columns::Int = -1,
    maximum_number_of_lines::Int = -1,
    parse_decorations_before_view::Bool = false,
    search_matches::Union{Nothing, Dict{Int, Vector{Tuple{Int, Int}}}} = nothing,
) where T<:AbstractString

I saw that the first call is taking 0.2s due to precompilation. I am trying to reduce it. I have already used SnoopCompile but I had minor gains, the precompilation is always happening when I first call the function. However, if I changed the signature to:

function textview(
    lines::Vector{String},
    view::NTuple{4, Int};
    active_highlight::String = _CSI * "30;43m",
    active_match::Int = 0,
    frozen_columns_at_beginning::Int = 0,
    frozen_lines_at_beginning::Int = 0,
    highlight::String = _CSI * "7m",
    maximum_number_of_columns::Int = -1,
    maximum_number_of_lines::Int = -1,
    parse_decorations_before_view::Bool = false,
    search_matches::Union{Nothing, Dict{Int, Vector{Tuple{Int, Int}}}} = nothing,
)

Then the first call take less than 10ms, meaning that the precompilation happened during the package build process.

Question: how can I do this using the first signature? I really need that first approach because it must work with Vector{SubString{String}}.

The information from SnoopCompile regarding inference time is:

julia> print_tree(tinf)
InferenceTimingNode: 0.192785/0.193579 on Core.Compiler.Timings.ROOT() with 1 direct children
└─ InferenceTimingNode: 0.000794/0.000794 on write(::IOBuffer, ::String, ::String, ::Vararg{String
}) with 0 direct children

I reduced the problem to this line!

        write(line_buf, line)

If I change it to:

        write(line_buf, string(line))

Everything is MUCH faster. I just cannot tell why this is happening.

I solved by adding the following to the package:

        let
            io = IOBuffer()
            write(io, SubString("test", 1, 4))
        end
1 Like

Shot in the dark: maybe JET.jl can tell you about type instabilities. And IIRC SnoopCompile has some support for JET.jl?

Thanks for the tip! I will search about it :slight_smile:

The concrete typing of the callee seems excessive. The more likely problem, as suggested by @goerch, is an inference problem in the caller.

SnoopCompile does support JET, but it also allows analysis of inference problems in it’s own right. It is both more and less comprehensive than JET: the differences are clarified in the first Note on this page. The short version is that JET is reproducible but only finds the first inference failure; SnoopCompile has to be run in a fresh session but finds all inference failures.

2 Likes

Good! I will try to analyze this. Thanks you very much for the information @tim.holy !

1 Like

@goerch and @tim.holy ,

Thank you very much for pointing out JET.jl! Using it, I found I had this in a part of the code:

        code_i = tryparse(Int, tokens[i], base = 10)

which can return nothing. Hence, I add:

        code_i = tryparse(Int, tokens[i], base = 10)
        isnothing(code_i) && continue

and now everything is working beautifully :slight_smile:

4 Likes

As usual thanks should go out to @aviatesk, likewise!

3 Likes

Thanks @aviatesk for this amazing tool! :slight_smile:

3 Likes