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

Make refresh rate of DeferredUpdateManager & TargetingTool configurable #550

Merged
merged 1 commit into from
Oct 22, 2024

Conversation

ptziegler
Copy link
Contributor

This adds a new setRefreshRate() for both classes, which defines how often paint requests are executed/the auto-exposer helper is evaluated.

Both tasks are currently executed as fast possible, which may lead to to a very high CPU cost with very little gain. By setting a high rate, users may artificially throttle the speed at which those operations are performed, at the cost of responsiveness.

Relates to:
#430
#492

@ptziegler
Copy link
Contributor Author

A follow-up to #494. After thinking about this topic for a while, I also came to the conclusion that dealing with system properties and alike is way too complicated, so I opted to a simple variable one can set.

@azoitl
Copy link
Contributor

azoitl commented Sep 6, 2024

I had a look at the timerExec and I don't think your patch does what you want it to do. If I understand it correctly you just delay every refresh request by the refresh rate but you are not reducing the number of refresh request, or?

Shouldn't all refresh requests that are arriving during during the refresh rate be discarded?

@ptziegler
Copy link
Contributor Author

Shouldn't all refresh requests that are arriving during during the refresh rate be discarded?

That should already be the case right now:

protected void queueWork() {
if (!updateQueued) {
sendUpdateRequest();
updateQueued = true;
}
}

The manager queues the update and then ignores everything that is submitted until the update is executed. This change simply delays the execution by a fixed amount of time.

In both cases, you will always have only one request scheduled at a time. But with the refresh rate, it'll be less requests per minute that are executed.

@azoitl
Copy link
Contributor

azoitl commented Sep 7, 2024

Thanks for the explanation. Yes that makes sense. I just tested it with larger diagrams (a few thousand figures) in 4diac IDE. I gave the UpdateManager of the editor a refresh rate of 20ms and the outline (which was up to now the bottleneck) 100ms. I didn't see any drawing artifacts, didn't notice any lag in refresh, and what it is most important it felt smother then before. However that is a bit subjective and so far I didn't find a good way to measure it.

@BauePhil you could give this patch a try to test if you get a better performance for your large Zest diagrams.

@ptziegler
Copy link
Contributor Author

However that is a bit subjective and so far I didn't find a good way to measure it.

I don't think there is, as I believe this to highly depend on the complexity of the model. For the targeting tool, 1ms seems to have been a good value, but even that is hard to check without a big sample size.
The sweet spot for their project is something people have to figure out on their own, I'm afraid.

This adds a new setRefreshRate() method to the Thumbnail,
DeferredUpdateManager and TargetingTool class which defines how
often UI events are executed.

By default, those events are executed as fast possible, which may lead
to to a very high CPU cost with very little gain. By setting a high
rate, users may artificially throttle the speed at which those
operations are performed, at the cost of responsiveness.

Relates to:
eclipse#430
eclipse#492
@ptziegler
Copy link
Contributor Author

@wiresketch

In #430 you said:

What I had in mind is reusing the same image for multiple paint calls without redrawing the buffered image each time.

Is this approach similar to what you had in mind? Reducing the number of executed paint requests should behave similar to repainting the same image over multiple calls. The "buffer" would then be whatever has been stored in the native widget and not be a separate Image.

Ideally, I'd like to finish this PR up for the next release, so that you and others can give it a go.

@ptziegler ptziegler marked this pull request as ready for review October 20, 2024 11:28
@ptziegler ptziegler requested a review from azoitl October 20, 2024 11:28
@azoitl
Copy link
Contributor

azoitl commented Oct 20, 2024

@ptziegler I gave it another try today. And I strongly believe that especially opening very large diagrams feels now much more responsive. So from my side I would merge it.

@azoitl azoitl merged commit 5c33111 into eclipse:master Oct 22, 2024
9 checks passed
@wiresketch
Copy link
Contributor

@wiresketch

In #430 you said:

What I had in mind is reusing the same image for multiple paint calls without redrawing the buffered image each time.

Is this approach similar to what you had in mind? Reducing the number of executed paint requests should behave similar to repainting the same image over multiple calls. The "buffer" would then be whatever has been stored in the native widget and not be a separate Image.

Ideally, I'd like to finish this PR up for the next release, so that you and others can give it a go.

I haven't got the time to test this issue, but looking at the code I am not sure how it buffers the updates? As far as can I see, Display#timerExec is always called with a new object (only in Thumbnail the same "this" reference is being used) so this only delays the execution of the Runnable. I would expect the same instance of the object to be used with timerExec to get the "buffering" effect, like it's done in Thumbnail. Am I wrong?

@ptziegler
Copy link
Contributor Author

As far as can I see, Display#timerExec is always called with a new object (only in Thumbnail the same "this" reference is being used) so this only delays the execution of the Runnable.

For e.g. the DeferredUpdateManager, most of the magic is done by the updateQueued flag. While the request is pending, all successive calls to the udpate method (e.g. during paint calls) are effectively skipped. By delaying the request execution, one can greatly reduce the number of repaints that are executed within a given amount of time.

protected void queueWork() {
if (!updateQueued) {
sendUpdateRequest();
updateQueued = true;
}
}

@ptziegler ptziegler added this to the 3.22.0 milestone Oct 22, 2024
@ptziegler ptziegler deleted the throttler branch October 22, 2024 14:20
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