JuliaFolds2 / BangBang.jl

Immutables as mutables, mutables as immutables.
https://juliafolds2.github.io/BangBang.jl/dev/
MIT License
14 stars 6 forks source link

Add precompilation workflows with PrecompileTools.jl #9

Open MasonProtter opened 1 year ago

MasonProtter commented 1 year ago

A nice beginner task for someone looking to help out would be to use PrecompileTools.jl to speed up the TTFX of this package.

kalmarek commented 1 year ago

Based on tests I've created a precompiletools.jl with @compile_workload;

However I don't really see any speedup (in tests) since most of the time is spent in test_dataframes.jl etc. which we won't precompile.

should we pursuit this further?

kalmarek commented 1 year ago

in comparison: with precompile_tools.jl:

julia> using Pkg; @time using BangBang; @time Pkg.test("BangBang"); @time Pkg.test("BangBang");

reports:

[ Info: Precompiling BangBang [198e06fe-97b7-11e9-32a5-e1d131e6ad66]
  7.507439 seconds (574.53 k allocations: 32.287 MiB, 0.88% gc time, 1.91% compilation time)
72.177451 seconds (3.59 M allocations: 298.980 MiB, 0.17% gc time, 2.18% compilation time: 7% of which was recompilation)
53.670724 seconds (673.94 k allocations: 66.323 MiB, 0.08% gc time)

vs baseline:

[ Info: Precompiling BangBang [198e06fe-97b7-11e9-32a5-e1d131e6ad66]
  0.835754 seconds (146.68 k allocations: 12.104 MiB, 8.54% gc time, 6.97% compilation time)
 62.217168 seconds (3.59 M allocations: 299.094 MiB, 0.14% gc time, 2.53% compilation time: 6% of which was recompilation)
 55.498739 seconds (674.17 k allocations: 66.300 MiB, 0.06% gc time)
MasonProtter commented 1 year ago

Hm yeah I guess that makes sense. What happens if you dont include dataframes?

kalmarek commented 1 year ago

If I comment both zygote and dataframes tests take here

# with precompiletools
49.497205 seconds (670.57 k allocations: 66.080 MiB, 0.03% gc time)
28.202651 seconds (681.65 k allocations: 66.782 MiB, 0.06% gc time

# without
36.329705 seconds (682.08 k allocations: 66.775 MiB, 0.04% gc time, 0.01% compilation time)
33.570996 seconds (681.95 k allocations: 66.791 MiB)

Unless we find some nice (and useful) workload, I'd rather not do it due to much increased precompile times...

the content of precompiletools.jl:

import PrecompileTools

PrecompileTools.@setup_workload begin

    xs = [1, 2, 3]

    PrecompileTools.@compile_workload begin
        add!!(1, 2)
        add!!((1,), (2,))
        add!!([1], [2])
        # add!!(SVector(1), SVector(2))
        # add!!(SVector(1), [2])
        # add!!([1], SVector(2))
        add!!([1], [0.5])

        append!!([0.0], [1.0])
        append!!([0], [1.0])
        append!!([0], (1.0,))
        append!!((0,), (1,))
        append!!((a=0,), pairs((b=1,)))
        append!!(Base.ImmutableDict(:a => 1), Base.ImmutableDict(:b => 2))
        append!!("a", "b")
        # append!!(SVector(0), [1])::Vector
        # append!!([0], SVector(1))::Vector
        append!!(Union{}[], Iterators.take(1:10, 3))
        append!!(SingletonVector(1), [0.5, 2])

        append!!(xs, InitialValue(append!!))
        append!!(InitialValue(append!!), xs)
        append!!(InitialValue(append!!), (x for x in xs if true))
        append!!(InitialValue(append!!), InitialValue(append!!))

        broadcast!!(+, xs, zeros(Int, 3), 1)
        broadcast!!(+, xs, [1, 2, 3], 0.5)
        Extras.broadcast_inplace!!(+, xs, 1)
        Extras.broadcast_inplace!!(+, xs, [1, 2, 3], 0.5)

        for unsafe in [false, true]
            n = 10
            for (label, src) in [
                "vector" => 1:n,
                "generator" => (x + 1 for x in 1:n),
                "filter" => (x for x in 1:n if isodd(x)),
            ]
                data = Vector{Int}(undef, n)
                c = collector(data, Val(unsafe))
                finish!(append!!(c, src))
            end
        end
        c1 = append!!(collector(), [1, 2])
        c2 = append!!(collector(), [3, 4, 5])
        finish!(append!!(c1, c2))

        delete!!(Dict(:a => 1), :a)
        delete!!((a=1,), :a)

        empty!!((1, 2, 3))
        empty!!((a=1, b=2, c=3))
        empty!!([1, 2, 3])

        lmul!!(1, 2)
        A = LowerTriangular(reshape(1:4, 2, 2))
        B = ones(2, 2)
        lmul!!(A, B)
        A = LowerTriangular(collect(Float64, reshape(1:4, 2, 2)))
        B = ones(Int, 2, 2)
        AB = A * B
        lmul!!(A, B)

        a0 = Real[1:3;]
        a = copy(a0)
        b = [0im] .+ (1:3)
        materialize!!(a, air.(a .+ b))

        for (args, desired) in Any[
            ((Dict(:a => 1), Dict(:b => 0.5)), Dict(:a => 1.0, :b => 0.5)),
            ((Dict(:a => 1), Dict("b" => 2)), Dict(:a => 1, "b" => 2)),
            ((Dict(:a => 1), Dict("b" => 0.5)), Dict(:a => 1.0, "b" => 0.5)),
            (((a=1,), (b=2,)), (a=1, b=2)),
            (((a=1,), Dict(:b => 2)), (a=1, b=2)),
            (((a=1,), Dict(:b => 2), (b=3,)), (a=1, b=3)),
            ((Empty(Dict), Dict(:a => 1)), Dict(:a => 1)),
            # ((Empty(Dict), SingletonDict(:a => 1)), Dict(:a => 1)),
            # ((SingletonDict(:a => 1), Dict(:b => 2)), Dict(:a => 1, :b => 2)),
            # ((SingletonDict(:a => 1), Dict(:a => 2)), Dict(:a => 2)),
            ((+, Dict(:a => 1), Dict(:a => 0.5)), Dict(:a => 1.5)),
            ((+, (a=1,), Dict(:a => 0.5)), (a=1.5,)),
        ]
            merge!!(args...)
        end
        for (args, desired) in Any[
            ((Dict(:a => 1), Dict(:b => 2)), Dict(:a => 1, :b => 2)),
            ((Dict(:a => 1), (b=2,)), Dict(:a => 1, :b => 2)),
            ((+, Dict(:a => 1), Dict(:a => 2)), Dict(:a => 3)),
            ((+, Dict(:a => 1), (a=2,)), Dict(:a => 3)),
            ((+, Dict(:a => 1), (a=2,), Dict(:a => 3)), Dict(:a => 6)),
        ]
            merge!!(args...)
        end

        mul!!(0, 1, 2)
        mul!!(missing, 1, 2)
        mul!!(nothing, 1, 2)
        C = zeros(2, 2)
        A = reshape(1:4, 2, 2)
        B = ones(2, 2)
        mul!!(C, A, B)

        C = zeros(Int, size(A * B))
        mul!!(C, A, B)

        pop!!([0, 1])
        pop!!((0, 1))
        pop!!((a=0, b=1))
        # pop!!(SVector(0, 1))
        pop!!(Dict(:a => 1), :a)
        pop!!((a=1,), :a)
        pop!!(Dict(:a => 1), :a, nothing)

        popfirst!!([0, 1])
        popfirst!!((0, 1))
        popfirst!!((a=0, b=1))
        # popfirst!!(SVector(0, 1))

        push!!([0.0], 1.0)
        push!!([0], 1.0, 2im, UInt(3))
        push!!([0], 1.0)
        push!!((0,), 1)
        NoBang.push((0,), 1)
        push!!((0,), 1.0, 2im, UInt(3))
        NoBang.push((0,), 1.0, 2im, UInt(3))
        push!!((a=0,), :b => 1)
        push!!((a=0,), Val(:b) => 1)
        # push!!(SVector(0), 1)
        # push!!(SVector(0), 0.5)
        push!!(Base.ImmutableDict(:a => 1), :b => 2)
        push!!(Dict(), :a => 1)::Dict{Any,Any}
        push!!(Dict{Union{},Union{}}(), :a => 1)::Dict{Symbol,Int}
        push!!(Set(), 1)::Set{Any}
        push!!(Set{Union{}}(), 1)::Set{Int}

        pushfirst!!([0.0], 1.0)
        pushfirst!!([0], 1.0)
        pushfirst!!((0,), 1)
        # pushfirst!!(SVector(0), 1)
        # pushfirst!!(SVector(0), 1)

        rmul!!(1, 2)

        A = collect(Float64, reshape(1:4, 2, 2))
        B = UpperTriangular(ones(2, 2))
        rmul!!(A, B)

        A = collect(Int, reshape(1:4, 2, 2))
        B = UpperTriangular(ones(2, 2))
        rmul!!(A, B)::Matrix{Float64}

        setdiff!!([0], [0])
        setdiff!!([0], (0,))
        setdiff!!([0, 1, 2], (0,), [1])
        setdiff!!(Set([0]), [0])
        setdiff!!(Set([0]), (0,))
        setdiff!!(Set([0, 1, 2]), Set([0]), [1])
        setdiff!!(Empty(Vector), [])
        setdiff!!(Empty(Set{Int}), [])

        # setfield?

        setindex!!((1, 2, 3), :two, 2)
        setindex!!((a=1, b=2, c=3), :two, :b)
        setindex!!([1, 2, 3], :two, 2)
        setindex!!(Dict{Symbol,Int}(:a => 1, :b => 2), 10, :a)
        setindex!!(Dict{Symbol,Int}(:a => 1, :b => 2), 3, "c")

        setproperty!!((a=1, b=nothing), :b, 2)

        splice!!((1, 2, 3), 2)
        splice!!([1, 2, 3], 2)
        splice!!([1, 2, 3], 2, 20)
        splice!!((1, 2, 3), 2, 20)
        splice!!([1, 2, 3], 2:3)
        splice!!([1, 2, 3], 2:3, [20, 30])
        # splice!!(SVector(1, 2, 3), 2)
        # splice!!(SVector(1, 2, 3), 2, 20)

        union!!([0.0], [1.0])
        union!!([0], [0.5])
        union!!(Set([0.0]), [1.0])
        union!!(Set([0]), [0.5])
        union!!(Empty(Set), [0])
        union!!(Empty(Set), SingletonVector(0))

        union!!(Set([0]), InitialValue(union!!))

        unique!!([3, 2, 1, 2, 3])

    end
end