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

More latency/inferrability work #21

Closed
wants to merge 3 commits into from

Conversation

timholy
Copy link
Collaborator

@timholy timholy commented Jul 31, 2021

This is a fairly extensive/intrusive change aimed at further reducing GridLayoutBase's contribution to the overall Makie latency. It shaves about 15% off the time to run the test suite.

The biggest changes are to the types:

  • it makes Side and GridDir enums rather than types, to reduce the amount of compiler specialization
  • it improves inferrability of GridLayout by changing the type-parameters (I hope I did this correctly, not sure)
  • it switches to the Observables 0.4 style of doing business, and makes many Observables more inferrable

It also changes how the precompile file works. It may be slightly less comprehensive but far more portable.

You'll have to decide whether you think this is worthwhile, and if so on what schedule to adopt it.

As is presumably obvious, this is a breaking change.

@codecov-commenter
Copy link

codecov-commenter commented Jul 31, 2021

Codecov Report

Merging #21 (7d51444) into master (b514330) will decrease coverage by 70.44%.
The diff coverage is 38.57%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master      #21       +/-   ##
===========================================
- Coverage   87.00%   16.56%   -70.45%     
===========================================
  Files          10        9        -1     
  Lines        1170     1014      -156     
===========================================
- Hits         1018      168      -850     
- Misses        152      846      +694     
Impacted Files Coverage Δ
src/GridLayoutBase.jl 0.00% <ø> (-100.00%) ⬇️
src/gridlayoutspec.jl 0.00% <0.00%> (-100.00%) ⬇️
src/layoutobservables.jl 8.09% <0.00%> (-76.36%) ⬇️
src/geometry_integration.jl 5.26% <25.00%> (-94.74%) ⬇️
src/layout_engine.jl 37.33% <31.25%> (-44.42%) ⬇️
src/types.jl 34.78% <42.85%> (-65.22%) ⬇️
src/gridlayout.jl 17.18% <47.36%> (-76.72%) ⬇️
src/gridapi.jl 0.00% <0.00%> (-100.00%) ⬇️
... and 6 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b514330...7d51444. Read the comment docs.

@timholy
Copy link
Collaborator Author

timholy commented Jul 31, 2021

CC @SimonDanisch, @IanButterworth. This package was already in pretty good shape, latency-wise, but it illustrates the style I generally find useful more broadly.

@timholy
Copy link
Collaborator Author

timholy commented Aug 7, 2021

@jkrumbiegel, let me know if you're at all interested in this PR. If so I might be able to help get the module in Makie updated for this (and work on latency there too, which I suspect will be a more impactful change). If not, feel free to close.

Base.getindex(rowcols::RowCols, side::Side) = side == Left ? rowcols.lefts :
side == Right ? rowcols.rights :
side == Top ? rowcols.tops :
side == Bottom ? rowcols.bottoms : throw_side(side)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this style better than the dispatch version? aren't four methods compiled anyway?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see now that you've changed it to an enum

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this style with a couple of types should be avoided in general?

Copy link
Collaborator Author

@timholy timholy Aug 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends: if Side is effectively "closed" then an enum has a big advantage, but a big weakness if your goal is external extensibility. More detail: recall that Julia specializes methods for each specific argument type:

julia> abstract type StaticNumber <: Number end

julia> struct One <: StaticNumber end

julia> struct Two <: StaticNumber end

julia> f(n::StaticNumber) = nothing
f (generic function with 1 method)

julia> f(One())

julia> f(Two())

julia> using MethodAnalysis

julia> methodinstances(f)
2-element Vector{Core.MethodInstance}:
 MethodInstance for f(::One)
 MethodInstance for f(::Two)

That means f has to be compiled twice. That's not so bad for such simple f, but if it has n arguments and each comes in 2 flavors then pretty soon you're at 2^n combinations, which is a big big problem. But with this version:

julia> @enum StaticNumber One Two

julia> f(n::StaticNumber) = nothing
f (generic function with 1 method)

julia> f(One)

julia> f(Two)

julia> using MethodAnalysis

julia> methodinstances(f)
1-element Vector{Core.MethodInstance}:
 MethodInstance for f(::StaticNumber)

it only has to be compiled once. If you have several such arguments to a multi-argument function, the resulting savings/costs can be quite large. This will presumably be more impactful in Makie itself which adds a lot more types.

The downside is that you can no longer use dispatch to extend Side unless you do it in this package. As long as you're OK with that, the advantages here are surely worth having.

valign = :center,
default_rowgap = DEFAULT_ROWGAP_GETTER[](),
default_colgap = DEFAULT_COLGAP_GETTER[](),
halign::AlignAttribute = :center,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle, an align is just a float. The symbols are just because this is directly user facing, and it's nicer to write :right rather than 1. But I already feared that these type instabilities that propagate relatively far into the code aren't good.

observablify(x, type=Any) = Observable{type}(x)
observablify(x) = Observable(x)
struct Observablify{T} end
Observablify{T}(x) where T = convert(Observable{T}, x)::Observable{T}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of this struct? isn't it weird to have a constructor Observablify that creates an Observable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll change this. I can't remember right now why a regular function call didn't seem adequate.

# These don't work completely but they have partial success
@warnpcfail precompile(repr, (MIME{Symbol("text/plain")}, GridLayout))
let
while true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this while true do?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forces it to be compiled. Code at toplevel is often run in the interpreter, but we have a heuristic that says anything with a loop in it should be compiled because we know the interpreter is really slow and there's no way to know in general how many iterations the loop will have.

I'll add a comment about this.

Copy link
Owner

@jkrumbiegel jkrumbiegel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work, Tim! Sorry for the delay, I'm again a bit short on time these days, and this looked like a lot. Although now it seems there are mostly a few things that cause many changed lines, but are not so complex in themselves. I've commented on some things that I didn't understand when reading through.

@timholy
Copy link
Collaborator Author

timholy commented Aug 7, 2021

No worries! Thanks for the review, mostly I just wanted to know whether you appreciated this or whether it wasn't helpful.

I notice Makie is still on v0.5.5 for this package. Would it be premature to start upgrading it for this PR? I'm guessing the big hurdle is upgrading Makie to GeometryBasics 0.4? How bad is that likely to be?

@timholy
Copy link
Collaborator Author

timholy commented Feb 8, 2022

The good parts of this were done better in #30. Thanks again, @jkrumbiegel!

@timholy timholy closed this Feb 8, 2022
@timholy timholy deleted the teh/inference branch February 8, 2022 13:18
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

Successfully merging this pull request may close these issues.

3 participants