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

improve compile latency #1686

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions CairoMakie/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

[compat]
Cairo = "1.0.4"
Expand All @@ -24,7 +23,6 @@ FileIO = "1.1"
FreeType = "3, 4.0"
GeometryBasics = "0.4.1"
Makie = "=0.16.5"
StaticArrays = "0.12, 1.0"
julia = "1.3"

[extras]
Expand Down
8 changes: 7 additions & 1 deletion CairoMakie/src/CairoMakie.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module CairoMakie

using Makie, LinearAlgebra
using Colors, GeometryBasics, FileIO, StaticArrays
using Colors, GeometryBasics, FileIO
import SHA
import Base64
import Cairo
Expand Down Expand Up @@ -61,4 +61,10 @@ function activate!(; inline = _last_inline[], type = _last_type[], px_per_unit=_
return
end

if Base.VERSION >= v"1.4.2"
include("precompiles.jl")
_precompile_()
end


end
3 changes: 2 additions & 1 deletion CairoMakie/src/infrastructure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ function cairo_draw(screen::CairoScreen, scene::Scene)
draw_background(screen, scene)

allplots = get_all_plots(scene)
sort!(allplots, by = Makie.zvalue2d)
zvals = Makie.zvalue2d.(allplots)
permute!(allplots, sortperm(zvals))

last_scene = scene

Expand Down
10 changes: 10 additions & 0 deletions CairoMakie/src/precompiles.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
precompile(Makie.backend_display, (CairoBackend, Scene))
activate!()
f, ax1, pl = scatter(1:4)
f, ax2, pl = lines(1:4)
Makie.colorbuffer(ax1.scene)
Makie.colorbuffer(ax2.scene)
return
end
32 changes: 15 additions & 17 deletions CairoMakie/src/primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -320,14 +320,12 @@ function draw_atomic(scene::Scene, screen::CairoScreen, primitive::Text{<:Tuple{
position = primitive.position[]
# use cached glyph info
glyph_collection = to_value(primitive[1])

draw_glyph_collection(scene, ctx, position, glyph_collection, remove_billboard(rotation), model, space, offset)

nothing
end


function draw_glyph_collection(scene, ctx, positions, glyph_collections::AbstractArray, rotation, model::SMatrix, space, offset)
function draw_glyph_collection(scene, ctx, positions, glyph_collections::AbstractArray, rotation, model::Mat, space, offset)

# TODO: why is the Ref around model necessary? doesn't broadcast_foreach handle staticarrays matrices?
broadcast_foreach(positions, glyph_collections, rotation,
Expand Down Expand Up @@ -404,15 +402,15 @@ function draw_glyph_collection(scene, ctx, position, glyph_collection, rotation,
glyphpos = let
# project without yflip - we need to apply model before that
p = project_position(scene, position, Mat4f(I), false)

# flip for Cairo
p += (p3_to_p2(glyphoffset .+ p3_offset))
p = (_deref(model) * Vec4f(p[1], p[2], 0, 1))[Vec(1, 2)]
p = (0, 1) .* scene.camera.resolution[] .+ p .* (1, -1)
p
end
# and the scale is just taken as is
scale = length(scale) == 2 ? scale : SVector(scale, scale)
scale = length(scale) == 2 ? scale : Vec(scale, scale)

mat = let
scale_mat = if length(scale) == 2
Expand Down Expand Up @@ -597,11 +595,11 @@ function draw_atomic(scene::Scene, screen::CairoScreen, primitive::Union{Heatmap

# Rectangles and polygons that are directly adjacent usually show
# white lines between them due to anti aliasing. To avoid this we
# increase their size slightly.
# increase their size slightly.

if alpha(colors[i, j]) == 1
# sign.(p - center) gives the direction in which we need to
# extend the polygon. (Which may change due to rotations in the
# sign.(p - center) gives the direction in which we need to
# extend the polygon. (Which may change due to rotations in the
# model matrix.) (i!=1) etc is used to avoid increasing the
# outer extent of the heatmap.
center = 0.25 * (p1 + p2 + p3 + p4)
Expand Down Expand Up @@ -691,9 +689,9 @@ function draw_mesh3D(
@get_attribute(primitive, (color, shading, diffuse,
specular, shininess, faceculling))

colormap = get(primitive, :colormap, nothing) |> to_value |> to_colormap
colorrange = get(primitive, :colorrange, nothing) |> to_value
matcap = get(primitive, :matcap, nothing) |> to_value
colormap = to_colormap(to_value(get(primitive, :colormap, nothing)))
colorrange = to_value(get(primitive, :colorrange, nothing))
matcap = to_value(get(primitive, :matcap, nothing))
# Priorize colors of the mesh if present
color = hasproperty(mesh, :color) ? mesh.color : color

Expand All @@ -702,7 +700,7 @@ function draw_mesh3D(
model = primitive.model[]
view = scene.camera.view[]
projection = scene.camera.projection[]
i = SOneTo(3)
i = Vec(1, 2, 3)
normalmatrix = transpose(inv(view[i, i] * model[i, i]))

# Mesh data
Expand All @@ -721,9 +719,9 @@ function draw_mesh3D(
ns = map(n -> normalize(normalmatrix * n), decompose_normals(mesh))
cols = per_face_colors(
color, colormap, colorrange, matcap, vs, fs, ns, uv,
get(primitive, :lowclip, nothing) |> to_value |> color_or_nothing,
get(primitive, :highclip, nothing) |> to_value |> color_or_nothing,
get(primitive, :nan_color, nothing) |> to_value |> color_or_nothing
color_or_nothing(to_value(get(primitive, :lowclip, nothing))) ,
color_or_nothing(to_value(get(primitive, :highclip, nothing))) ,
color_or_nothing(to_value(get(primitive, :nan_color, nothing)))
)

# Liight math happens in view/camera space
Expand All @@ -750,7 +748,7 @@ function draw_mesh3D(
@inbounds begin
p = (clip ./ clip[4])[Vec(1, 2)]
p_yflip = Vec2f(p[1], -p[2])
p_0_to_1 = (p_yflip .+ 1f0) / 2f0
p_0_to_1 = (p_yflip .+ 1f0) ./ 2f0
end
p = p_0_to_1 .* scene.camera.resolution[]
return Vec3f(p[1], p[2], clip[3])
Expand All @@ -772,7 +770,7 @@ function draw_mesh3D(
map(ns[f], vs[f], cols[k]) do N, v, c
L = normalize(lightpos .- v[Vec(1,2,3)])
diff_coeff = max(dot(L, N), 0.0)
H = normalize(L + normalize(-v[SOneTo(3)]))
H = normalize(L + normalize(-v[Vec(1, 2, 3)]))
spec_coeff = max(dot(H, N), 0.0)^shininess
c = RGBA(c)
new_c = (ambient .+ diff_coeff .* diffuse) .* Vec3f(c.r, c.g, c.b) .+
Expand Down
4 changes: 2 additions & 2 deletions CairoMakie/src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function project_position(scene, point, model, yflip = true)
# flip y to match cairo
p_yflip = Vec2f(p[1], (1f0 - 2f0 * yflip) * p[2])
# normalize to between 0 and 1
p_0_to_1 = (p_yflip .+ 1f0) / 2f0
p_0_to_1 = (p_yflip .+ 1f0) ./ 2f0
end
# multiply with scene resolution for final position
return p_0_to_1 .* res
Expand Down Expand Up @@ -189,7 +189,7 @@ Base.getindex(fi::FaceIterator{:PerFace}, i::Integer) = fi.data[i]
Base.getindex(fi::FaceIterator{:PerVert}, i::Integer) = fi.data[fi.faces[i]]
Base.getindex(fi::FaceIterator{:Const}, i::Integer) = ntuple(i-> fi.data, 3)

color_or_nothing(c) = c === nothing ? nothing : to_color(c)
color_or_nothing(c) = isnothing(c) ? nothing : to_color(c)

function per_face_colors(
color, colormap, colorrange, matcap, vertices, faces, normals, uv,
Expand Down
2 changes: 0 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
Showoff = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
SignedDistanceFields = "73760f76-fbc4-59ce-8f25-708e95d2df96"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
Expand Down Expand Up @@ -83,7 +82,6 @@ PolygonOps = "0.1.1"
RelocatableFolders = "0.1"
Showoff = "0.3, 1.0.2"
SignedDistanceFields = "0.4"
StaticArrays = "0.12, 1.0"
StatsBase = "0.31, 0.32, 0.33"
StatsFuns = "0.9"
StructArrays = "0.3, 0.4, 0.5, 0.6"
Expand Down
5 changes: 5 additions & 0 deletions metrics/ttfp/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
6 changes: 6 additions & 0 deletions metrics/ttfp/benchmark-ttfp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

t_using = (tstart = time(); using CairoMakie; time() - tstart)

t_plot = (tstart = time(); save("test.png", scatter(1:4)); time() - tstart)
rm("test.png")
println("($t_using, $t_plot)")
Binary file added metrics/ttfp/data/julia_17_latency.jls
Binary file not shown.
Binary file added metrics/ttfp/data/julia_19_latency.jls
Binary file not shown.
Binary file added metrics/ttfp/data/julia_19_precompile.jls
Binary file not shown.
4 changes: 4 additions & 0 deletions metrics/ttfp/makie-precompile/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
2 changes: 2 additions & 0 deletions metrics/ttfp/makie-tagged/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
50 changes: 50 additions & 0 deletions metrics/ttfp/track_pr_ttfp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Pkg
cd(@__DIR__)
Pkg.activate(".")
pkg"dev ../../MakieCore/ ../../ ../../CairoMakie/; add GeometryBasics#sd/no-sarray"

using Pkg
Pkg.activate("./makie-tagged")
pkg"add CairoMakie"
Pkg.precompile("CairoMakie")

function run_bench(julia, project, n=10)
results = Tuple{Float64, Float64}[]
for i in 1:n
result = read(`$(julia) --project=$(project) ./benchmark-ttfp.jl`, String)
tup = eval(Meta.parse(result))
@show tup
push!(results, tup)
end
return results
end

julia_th = "./../../../../julia_th/julia"
julia_17 = "julia"

result_1_7 = run_bench(julia_17, ".")
result_th = run_bench(julia_th, ".")
result_1_7_tagged = run_bench(julia_17, "makie-tagged")
result_th_tagged = run_bench(julia_th, "makie-tagged")

using Pkg
Pkg.activate("./makie-precompile")
pkg"add Makie#sd/more-precompile CairoMakie#sd/more-precompile"
Pkg.precompile("CairoMakie")

result_1_7_precompile = run_bench(julia_17, "makie-precompile")
result_th_precompile = run_bench(julia_th, "makie-precompile")

using Serialization

open("./data/julia_19_precompile.jls", "w") do io
Serialization.serialize(io, result_th_precompile)
end

open("./data/julia_19_latency.jls", "w") do io
Serialization.serialize(io, result_th)
end

open("./data/julia_17_latency.jls", "w") do io
Serialization.serialize(io, result_1_7)
end
8 changes: 6 additions & 2 deletions src/Makie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ using Markdown
using DocStringExtensions # documentation
using Serialization # serialize events
using StructArrays
using StaticArrays
# Text related packages
using FreeType
using FreeTypeAbstraction
Expand All @@ -48,7 +47,7 @@ import SparseArrays
using MakieCore
using OffsetArrays

using GeometryBasics: widths, positive_widths, VecTypes, AbstractPolygon, value
using GeometryBasics: widths, positive_widths, VecTypes, AbstractPolygon, value, StaticVector
using Distributions: Distribution, VariateForm, Discrete, QQPair, pdf, quantile, qqbuild

import FileIO: save
Expand Down Expand Up @@ -297,4 +296,9 @@ export heatmap!, image!, lines!, linesegments!, mesh!, meshscatter!, scatter!, s

export PointLight, EnvironmentLight, AmbientLight, SSAO

if Base.VERSION >= v"1.4.2"
include("precompiles.jl")
_precompile_()
end

end # module
2 changes: 1 addition & 1 deletion src/basic_recipes/axis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ function draw_axis3d(textbuffer, linebuffer, scale, limits, ranges_labels, args.
axisnames_size = (%) .* axisnames_size

# index of the direction in which ticks and labels are drawn
offset_indices = [ifelse(i != 2, mod1(i + 1, N), 1) for i in 1:N]
offset_indices = Vec(ntuple(i-> ifelse(i != 2, mod1(i + 1, N), 1), N))
# These need the real limits, not (%), to be scale-aware
titlegap = 0.01limit_widths[offset_indices] .* titlegap
tgap = 0.01limit_widths[offset_indices] .* tgap
Expand Down
4 changes: 2 additions & 2 deletions src/camera/camera.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ end
When mapping over observables for the camera, we store them in the `steering_node` vector,
to make it easier to disconnect the camera steering signals later!
"""
function Observables.on(f::Function, camera::Camera, observables::AbstractObservable...; priority=Int8(0))
function Observables.on(f, camera::Camera, observables::AbstractObservable...; priority=Int8(0))
# PriorityObservables don't implement on_any, because that would replace
# the method in Observables. CameraLift acts as a workaround for now.
cl = CameraLift(f, observables)
Expand All @@ -81,7 +81,7 @@ function Camera(px_area)
view = Observable(Mat4f(I))
proj = Observable(Mat4f(I))
proj_view = map(*, proj, view)
Camera(
return Camera(
pixel_space,
view,
proj,
Expand Down
25 changes: 18 additions & 7 deletions src/camera/camera2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,6 @@ function reset!(cam, boundingbox, preserveratio = true)
return
end



function add_restriction!(cam, window, rarea::Rect2, minwidths::Vec)
area_ref = Base.RefValue(cam[Area])
restrict_action = paused_action(1.0) do t
Expand Down Expand Up @@ -303,6 +301,20 @@ function add_restriction!(cam, window, rarea::Rect2, minwidths::Vec)
end

struct PixelCamera <: AbstractCamera end


struct UpdatePixelCam
camera::Camera
near::Float32
far::Float32
end

function (cam::UpdatePixelCam)(window_size)
w, h = Float32.(widths(window_size))
projection = orthographicprojection(0f0, w, 0f0, h, cam.near, cam.far)
set_proj_view!(cam.camera, projection, Mat4f(I))
end

"""
campixel!(scene; nearclip=-1000f0, farclip=1000f0)

Expand All @@ -311,12 +323,11 @@ Creates a pixel-level camera for the `Scene`. No controls!
function campixel!(scene; nearclip=-10_000f0, farclip=10_000f0)
disconnect!(camera(scene))
update_once = Observable(false)
on(camera(scene), update_once, pixelarea(scene)) do u, window_size
w, h = Float32.(widths(window_size))
projection = orthographicprojection(0f0, w, 0f0, h, nearclip, farclip)
set_proj_view!(camera(scene), projection, Mat4f(I))
end
closure = UpdatePixelCam(camera(scene), nearclip, farclip)
on(closure, camera(scene), pixelarea(scene))
cam = PixelCamera()
# update once
closure(pixelarea(scene)[])
cameracontrols!(scene, cam)
update_once[] = true
return cam
Expand Down
2 changes: 1 addition & 1 deletion src/camera/camera3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ function update_cam!(scene::Scene, camera::Camera3D, area3d::Rect)
@extractvalue camera (lookat, eyeposition, upvector)
bb = Rect3f(area3d)
width = widths(bb)
half_width = width/2f0
half_width = width ./ 2f0
middle = maximum(bb) - half_width
old_dir = normalize(eyeposition .- lookat)
camera.lookat[] = middle
Expand Down
6 changes: 3 additions & 3 deletions src/camera/projection_math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ function orthographicprojection(
end

function orthographicprojection(
left ::T, right::T,
bottom::T, top ::T,
znear ::T, zfar ::T
left::T, right::T,
bottom::T, top::T,
znear::T, zfar::T
) where T
(right==left || bottom==top || znear==zfar) && return Mat{4,4,T}(I)
T0, T1, T2 = zero(T), one(T), T(2)
Expand Down
4 changes: 2 additions & 2 deletions src/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -741,9 +741,9 @@ convert_attribute(p::Nothing, ::key"lowclip") = p
convert_attribute(p, ::key"nan_color") = to_color(p)

struct Palette{N}
colors::SArray{Tuple{N},RGBA{Float32},1,N}
colors::Vec{N, RGBA{Float32}}
i::Ref{UInt8}
Palette(colors) = new{length(colors)}(SVector{length(colors)}(to_color.(colors)), zero(UInt8))
Palette(colors) = new{length(colors)}(Vec{length(colors)}(to_color.(colors)), zero(UInt8))
end
Palette(name::Union{String, Symbol}, n = 8) = Palette(to_colormap(name, n))

Expand Down
Loading