I tried to create an WPF application that used a graph with LineRenderableSeriesViewModel
and XYDataSeries
to display real-time data. Cursor inspection was added to the chart as shown in the picture to make it easier to view the data. After some time I found out that when inspecting the cursor, if you move it quickly inside the chart, the CPU load increases several times.
Is there any elegant way to preserve performance with such manipulations?
My computer has a pretty good build but on weaker computers it causes some problems.
- Processor: AMD Ryzen 7 5825U with Radeon Graphics 2.00 GHz
- RAM: 16.0 GB (14.8 GB usable)
- System: Windows 11 Pro (21H2)
-
Good morning Kostiantyn, other than slightly higher cpu usage, are there any other negative effects when scrubbing the cursor on your application? CPU can be 100% but as long as the application(s) perform well it’s not a problem.
-
Yes, it only affects CPU load, the program runs as smoothly as before the actions. Problems may start only if it is run by a slow computer, then with increased CPU load and old graphics core the program starts to run slower. Is there any way to optimize this for slow devices?
-
OK got it. Optimising the hit-test is possible (there are still some optimisations we haven’t done here), but a more effective method may just be throttling the mouse-events (having fewer inspections per second of the cursor/tooltip). Let me circle back to the team and ask – Andrew
- You must login to post comments
Hi Kostiantyn,
Thanks for your question. I belive you are referring to RolloverModifier since it is shown on the screenshots – please correct me if Im wrong.
Using RolloverModifier may cause performance issues because it perfroms multiple hit-test operations (for every RenderableSeries) on every Mouse Move event.
As Andrew mentioned in the comments, the most obvious solution would be adding mouse events throttling for RolloverModifier. It should be not hard to implement. You could try doing that on your side by deriving a class from RolloverModifier and overridding OnModifierMouseMove(…) method in it. Then, debounce all method calls (or hit-test operations) until there is a pause long enough.
This can be implemented using Reactive Extensions or simply a timer. The implementation below should demostrate the idea:
public class RolloverModifierEx : RolloverModifier
{
private ModifierMouseArgs _last = null;
private bool _isUpdating = false;
private System.Timers.Timer _timer = new()
{
Interval = 100,
AutoReset = false
};
public RolloverModifierEx()
{
_timer.Elapsed += OnTimerElapsed;
}
private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
_isUpdating = false;
Dispatcher.InvokeAsync(() => base.OnModifierMouseMove(_last), DispatcherPriority.Send);
}
public override void OnModifierMouseMove(ModifierMouseArgs e)
{
_last = e;
// Restart updating timer
_timer.Stop();
_timer.Start();
_isUpdating = true;
base.OnModifierMouseMove(e);
// Alternatively, hide Rollover by passing in an invalid location
//base.OnModifierMouseMove(new ModifierMouseArgs(new Point(double.NaN, double.NaN), e.MouseButtons, e.Modifier, e.IsMaster, e.Source));
}
protected override IEnumerable<SeriesInfo> GetSeriesInfoAt(Point point)
{
// Prevent hit-test while mouse is moving
return _isUpdating ? Enumerable.Empty<SeriesInfo>() : base.GetSeriesInfoAt(point);
}
}
Please try this solution and let me know if it works as expected.
Best Regards,
Joeri
- Joeri R answered 1 year ago
- You must login to post comments
Please login first to submit.