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 accuracy of set framerate in GLMakie #3954

Merged
merged 12 commits into from
Jul 25, 2024
Merged

Conversation

ffreyer
Copy link
Collaborator

@ffreyer ffreyer commented Jun 11, 2024

Description

When targeting a framerate GLMakie uses sleep() which is pretty bad at its job:
Screenshot 2024-06-08 154030

And thus the frametimes are pretty off. For the default 30fps GLMakie targets we should have 1/30 = 0.033s delay between frames but I get around 0.045:
Screenshot 2024-06-10 220324

This pr adds some bookkeeping for the used time per frame. If one frame sleeps for too long the next frame will know about it and sleep for less time. This averages out the frametimes to match the requested framerate.

Screenshot 2024-06-11 214118

An alternative option would be have a while (current_time < frametime) yield() which would be better for stability but I assume would be worse for power usage.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • Added an entry in CHANGELOG.md (for new features and breaking changes)
  • Added or changed relevant sections in the documentation
  • Added unit tests for new algorithms, conversion methods, etc.
  • Added reference image tests for new plotting functions, recipes, visual options, etc.

@ffreyer ffreyer added the GLMakie This relates to GLMakie.jl, the OpenGL backend for Makie. label Jun 11, 2024
@MakieBot
Copy link
Collaborator

MakieBot commented Jun 11, 2024

Compile Times benchmark

Note, that these numbers may fluctuate on the CI servers, so take them with a grain of salt. All benchmark results are based on the mean time and negative percent mean faster than the base branch. Note, that GLMakie + WGLMakie run on an emulated GPU, so the runtime benchmark is much slower. Results are from running:

using_time = @ctime using Backend
# Compile time
create_time = @ctime fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @ctime Makie.colorbuffer(display(fig))
# Runtime
create_time = @benchmark fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @benchmark Makie.colorbuffer(fig)
using create display create display
GLMakie 4.55s (4.40, 4.66) 0.10+- 113.21ms (106.17, 119.99) 5.11+- 566.43ms (541.16, 584.10) 16.45+- 9.17ms (8.79, 9.64) 0.32+- 26.69ms (26.26, 27.18) 0.29+-
master 4.62s (4.54, 4.72) 0.06+- 120.24ms (111.70, 124.89) 4.56+- 583.41ms (552.34, 611.86) 19.48+- 9.57ms (9.01, 10.03) 0.36+- 26.62ms (26.10, 26.90) 0.34+-
evaluation 1.02x invariant, -0.07s (-0.82d, 0.16p, 0.08std) 1.06x faster✅, -7.03ms (-1.45d, 0.02p, 4.83std) 1.03x invariant, -16.98ms (-0.94d, 0.10p, 17.96std) 1.04x faster ✓, -0.41ms (-1.20d, 0.05p, 0.34std) 1.00x invariant, 0.08ms (0.24d, 0.66p, 0.31std)
CairoMakie 3.87s (3.68, 4.00) 0.13+- 113.36ms (109.24, 126.20) 5.83+- 136.96ms (131.80, 149.31) 6.03+- 8.57ms (8.13, 8.86) 0.26+- 980.86μs (970.65, 1005.59) 11.93+-
master 3.77s (3.67, 3.85) 0.08+- 110.70ms (106.02, 115.09) 3.54+- 136.00ms (129.30, 141.88) 5.06+- 8.43ms (8.18, 8.79) 0.19+- 986.62μs (974.12, 996.22) 8.21+-
evaluation 0.97x invariant, 0.1s (0.96d, 0.10p, 0.10std) 0.98x invariant, 2.66ms (0.55d, 0.33p, 4.68std) 0.99x invariant, 0.96ms (0.17d, 0.75p, 5.55std) 0.98x invariant, 0.14ms (0.61d, 0.28p, 0.22std) 1.01x invariant, -5.75μs (-0.56d, 0.32p, 10.07std)
WGLMakie 4.73s (4.68, 4.82) 0.05+- 112.57ms (109.06, 118.52) 3.45+- 9.60s (9.43, 9.76) 0.15+- 10.08ms (9.63, 10.27) 0.22+- 71.74ms (70.81, 72.61) 0.60+-
master 4.73s (4.68, 4.78) 0.03+- 112.47ms (110.55, 114.57) 1.79+- 9.52s (9.41, 9.59) 0.07+- 10.29ms (9.78, 11.42) 0.56+- 71.49ms (70.95, 71.88) 0.39+-
evaluation 1.00x invariant, -0.01s (-0.12d, 0.82p, 0.04std) 1.00x invariant, 0.11ms (0.04d, 0.94p, 2.62std) 0.99x invariant, 0.08s (0.67d, 0.25p, 0.11std) 1.02x invariant, -0.21ms (-0.49d, 0.39p, 0.39std) 1.00x invariant, 0.25ms (0.49d, 0.38p, 0.50std)

@jkrumbiegel
Copy link
Member

I saw something on discourse where they were using a different sleep function for higher accuracy, is that an option?

@ffreyer
Copy link
Collaborator Author

ffreyer commented Jun 11, 2024

I came across https://discourse.julialang.org/t/accuracy-of-sleep/5546 / JuliaLang/julia#12770 but on windows Base.Libc.systemsleep() behaves the same as sleep() for me.

@ffreyer ffreyer mentioned this pull request Jun 23, 2024
5 tasks
Comment on lines +14 to +16
function BudgetedTimer(callback, delta_time::Float64, running::Bool, task::Union{Nothing, Task}, min_sleep = 0.015)
return new(callback, delta_time, min_sleep, 0.0, time_ns(), running, task)
end
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I tried timing sleep(0.0001) here but it ended up being inconsistent. Most are 0.015s for me, but some are <0.005s and I assume async tasks and GC can also prolong them. So I just switched to a default value instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since I wasn't sure anymore I did some testing on what effect a wrong min_sleep has. Doesn't seem like there are any significant changes:
Screenshot 2024-07-25 134212
Screenshot 2024-07-25 134657

@ffreyer ffreyer marked this pull request as ready for review June 28, 2024 15:02
@SimonDanisch SimonDanisch merged commit 9c3f3e3 into master Jul 25, 2024
18 checks passed
@SimonDanisch SimonDanisch deleted the ff/frame_time_budget branch July 25, 2024 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GLMakie This relates to GLMakie.jl, the OpenGL backend for Makie.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants