Hi!
I am facing some performance issues when using a XamDataChart.
I've an example, taken from another post
https://es.infragistics.com/community/forums/f/ultimate-ui-for-wpf/70986/how-to-bind-multiple-collections-to-single-xamdatachart
I modified this example a little bit so that multiple signals are bound to one common x-axis and one common y-xaxis. There are 5 different signals, each consisting of about 10000 points randomly generated. When a signal is selected or deselected in the listbox the update of the XamDataChart is fast.
This is my first example:
Ex1.zip
Then I modified this example further to include an algorithm to compute a specific signal, 5 times the same signal. This signal is a rectangular signal consisting of about 480 points. Here the update of the XamDataChart is pretty slow (compared to example 1 with about 10000 points)
Ex2.zip
Where does this performance degradation come from?!
How can I increase the performance?!
Best regards,
Christoph
Hello Christoph,
I have been investigating into this behavior that you are referring to, and unfortunately, this is a known limitation of the XamDataChart of the control imposed by the WPF rendering methods used for the chart, and there isn't really too much we can do about it without introducing our own rendering methods.
Essentially, WPF does not play well with a highly fluctuating, seemingly random set of XamDataChart points here because of the Path that is generated as a result of these points. If you were to profile your application using a sort of diagnostic tool, I would imagine that you would see that most of the performance time spent here is in WPF's hardware rasterizer. WPF uses hardware acceleration as its default rendering mechanism, which means it uses Direct2D for rendering via the GPU. This normally makes performance faster, but there is an issue with Direct2D with this type of highly fluctuating shape, in which the rendering algorithm does not work well. This leads to Direct2D needing to do some conversions with the WPF path data, which makes the rendering operations happen primarily on the CPU rather than the GPU, and so there is a performance issue in WPF with this type of fluctuating path geometry.
One question I would like to know in this case is if your real-world data will look like this, or if it will be more linear with less fluctuation? For example, if you take a look at the following forum thread where a similar issue was discussed, I have attached a more-linear sample project with a series that has 1 million data points and the performance is very responsive: https://es.infragistics.com/community/forums/p/108504/511375.aspx.
If your real-world data will look like this, it is worth re-noting that this issue has come up in the past, and one of our developers has designed a custom-series workaround that uses a custom rendering method to get around this issue. Personally, I don't completely understand a good part of it, but from what I do understand is that it uses a class called WriteableBitmapEx to render the complex geometry of the series' path figure into a bitmap image, which it can then render to the screen. Essentially, it is a custom series with a custom renderer that bypasses the WPF bottleneck that you currently see with the existing series implementations in the XamDataChart, although this series is much less feature-rich than the ones that currently exist in the chart as it is not an "official" series. It is also not maintained, as it is not part of the Infragistics WPF product. You can find more information about the WriteableBitmapEx class here: https://writeablebitmapex.codeplex.com/.
I have also attached the sample project that was created some time ago that uses the custom "ImmediateLineSeries" that works around this issue. Simply check any number of checkboxes at the top of the application and then click one of the radio buttons to specify the number of points that you wish to show in a highly fluctuating, but still very responsive plot.
If you would like to see the ImmediateLineSeries solution more fleshed out into a fully supported series, or perhaps added as a separate rendering method for the chart, I would recommend suggesting a new product idea for this at our WPF Ideas Site, here. This will place you in direct communication with our product management teams who plan and prioritize upcoming features and development based on community and user feedback.
Please let me know if you have any other questions or concerns on this matter.
XamDataChartNoiseDataDemo.zip
Hi Andrew!
Thanks for your investigations.
It is not exactly 100% real world, but it is used to model the signal of a crankshaft position sensor
Information about crankshaft position sensor signals can be found i.e. on
https://gearsmagazine.com/magazine/crank-and-cam-part-ii-howsyour-relationship/
and
http://www.bosch-motorsport.de/content/downloads/Raceparts/Resources/pdf/HIL_Crankshaft_Camshaft_Simulation_75959563__LC_Test_System.pdf
where you will notice this "rectangular" shape.
I've another question in the forum, which deals with representing this signal. Although I've a "rectangular" shape defined by my data points I can only see some kind of "sawtooth" signal due to the rendering and also depending on the chart size.
Maybe it is worth to take a look at that also:
https://es.infragistics.com/community/forums/f/ultimate-ui-for-wpf/120513/winforms-chart-vs-xamdatachart-visual-representation-of-a-signal-facing-issue/533670
I did not notice the thread you mentioned
https://es.infragistics.com/community/forums/f/ultimate-ui-for-wpf/108504/datachart-scroll-zoom-performance/511375#511375
because it was related to scroll and zoom performance.
I tried the demo example attached to your reply, but was not able to run it. I currently have version 18.1.20181.324 installed and when compiling I get following error:
'Flattener' does not contain a definition for 'FastFlatten'
Not part of 18.1.20181.324 any more?!
BR, Christoph
I have done some more investigation into the ImmediateLineSeries in this case, and at the moment I am unsure why this is happening with the “Load Crank 1 Data” checkbox, but I can say it is due to the Resolution of the series in the case of the “Load Crank 2 Data” one. In the MainWindow.xaml.cs file, if you set the Resolution property of the ImmediateLineSeries to something very small – for example .001 – it will render a more representative shape for the series.
I believe the reason this is working is because the X-Values are different for each point, whereas with the “Crank 1 Data” there are two Y-Values per X-Value, and so something about the way that the ImmediateLineSeries might be only taking a single point in the actual rendering and so it is effectively simplifying the line. I can also confirm that this is specifically an issue with the ImmediateLineSeries, as if I switch to using a ScatterLineSeries (built-in) in the MainWindow.xaml.cs, it renders correctly, but the performance is not great as per the rendering issues mentioned in a previous post. The single point bit is only a guess, though, as the amount of experience you have had with the custom ImmediateLineSeries essentially matches mine. This series is not a part of the actual Infragistics WPF toolset, and if bugs or issues are found with it, it is not maintained or supported.
Hello Andrew!
In the meantime it is running in the Demo project. I started to change my main project and made following changes:
I added classes ImmediateLineSeries, ImmediateLineSeriesBaseView, ImmediateLineSeriesWBXView from the demo project to my main project
I added WriteableBitmapEx via NuGet
Replaced ScatterLineSeries
ScatterLineSeries series = new ScatterLineSeries();
series.XMemberPath = nameof(DataPoint.X);
series.YMemberPath = nameof(DataPoint.Y);
series.MarkerType = MarkerType.None;
series.SetBinding(ScatterLineSeries.XAxisProperty, new Binding { Source = chart.Axes[0] });
series.SetBinding(ScatterLineSeries.YAxisProperty, new Binding { Source = chart.Axes[1] });
series.SetBinding(ScatterLineSeries.DataContextProperty, new Binding { Source = sig });
series.SetBinding(ScatterLineSeries.ItemsSourceProperty, new Binding { Path = new PropertyPath(nameof(sig.Points)) });
series.SetBinding(ScatterLineSeries.TitleProperty, new Binding { Source = sig, Path = new PropertyPath(nameof(sig.SignalName)) });
with ImmediateLineSeries
ImmediateLineSeries.ImmediateLineSeries series = new ImmediateLineSeries.ImmediateLineSeries();
series.Thickness = 1;
series.Resolution = 0.001;
series.UseHairline = true;
series.UpscaleOPD = true;
series.SetBinding(ImmediateLineSeries.ImmediateLineSeries.XAxisProperty, new Binding { Source = chart.Axes[0] });
series.SetBinding(ImmediateLineSeries.ImmediateLineSeries.YAxisProperty, new Binding { Source = chart.Axes[1] });
series.SetBinding(ImmediateLineSeries.ImmediateLineSeries.DataContextProperty, new Binding { Source = sig });
series.SetBinding(ImmediateLineSeries.ImmediateLineSeries.ItemsSourceProperty, new Binding { Path = new PropertyPath(nameof(sig.Points)) });
series.SetBinding(ImmediateLineSeries.ImmediateLineSeries.TitleProperty, new Binding { Source = sig, Path = new PropertyPath(nameof(sig.SignalName)) });
No further code changes.
X-Axis (chart.Axes[0]) and Y-AXis (chart.Axes[1]) are defined in XAML
<ig:XamDataChart.Axes>
<ig:NumericXAxis x:Name="xAxis"/>
<ig:NumericYAxis x:Name="yAxis"/>
</ig:XamDataChart.Axes>
sig is an instance of Signal with properties SignalName and Points.
Points is of type ObservableCollection<DataPoint>
DataPoint has two properties: X and Y
When I run my application an System.OverflowException is thrown in ImmediateLineSeriesWBXView.OnResize
public override void OnResize(double width, double height)
due to width and height being -Inifity.
This method is called by ImmediateLineSeriesWBXView.PrepSurface when querying the Viewport for Thumbnail
if (IsThumbnail && OrderedScatterModel.UpscaleOPD) { Rect windowRect; Rect viewportRect; MainView.GetViewInfo(out viewportRect, out windowRect);
Viewport = viewportRect; }
I receive Viewport == Empty (empty size and all properties being equal to +/- infinite).
ImmediateLineSeriesWBXView.PrepSurface is called in ImmediateLineSeries.RenderThumbnail
ThumbView.PrepSurface(surface);
Any idea what can be the reason for that?!
Due to the nature that ImmediateLineSeries is not supported nor maintained, maybe it's will be the wrong way to go?!
It will be impossible to send my project, at least not on the forum. It contains a lot of references to other projects, too. So I will have to "clean up".
I am not certain, but it is possible that this error could potentially be caused by a missing default style for the ImmediateLineSeries. Did you include the Themes folder from the sample project I sent you so that the ImmediateLineSeries has a template? I am seeing a similar error in the sample project if I remove that folder.
I cannot really say if usage of the ImmediateLineSeries is really the “wrong” way to go, but with the current implementation of the series that are supported, the highly fluctuating path type will cause performance issues with essentially any line-type series. This is a current limitation of the XamDataChart imposed by WPF, and the ImmediateLineSeries was created as a “non-official workaround” in this case.
I included the Themes folder with the Generic.xaml into my solution.
Still the same exception.
Is it possible to send you my project (not inthe forum)?
In fact, I don't know what I am missing, or what I did wrong.
Thank you very much.
From my point of view I am ´happy.
Thank you for your update on this matter.
I have been investigating into the reason that the legend badge is not showing up correctly, and this is due to a problem with the Generic.xaml file, in that there does not exist an implicit legend badge for the ImmediateLineSeries, and so the binding that is in place in the LegendItemPointBadgeTemplate does not work.
In the attached modified sample, I replaced it with a Rectangle with its Fill bound to the ActualBrush of the series, and it is now showing up normally. I hope this helps you.
2604.XamDataChartNoiseDataDemo_LegendIssue.zip
Almost satisfied, but .... I've an issue with the legend.
When I use ScatterLineSeries, the legend looks similar to
but when I use ImmediateLineSeriesit looks like
it is not able to show the color of the series properly, instead it shows a undefined image/text, don't know.
I've modified your last example to include a legend:
XamDataChartNoiseDataDemo_LegendIssue.zip
If this can be solved, I have everything I need for the moment.
I would be also glad if it could become an "official" product, because I think that it is a good solution.
I have been investigating into the behavior you are seeing, and I am able to reproduce it, although I’m not sure why this happens in your sample but not in the one that I sent you.
It seems to me that there is something specifically about your dataset that is causing the Viewport of the thumbnail to return an {Empty} Rect with a height and width of different Infinite values, and this is where the issue lies. As such, I have implemented a workaround to check the Viewport for an Empty Rect in the ImmediateLineSeriesWBXView.PrepSurface method prior to calling OnResize as well as surrounding the RenderFrame call in the RenderThumbnail method in ImmediateLineSeries in a try-catch statement. This appears to fix the issue you are seeing and allow the overview plus detail pane to render correctly.
I am attaching a modified version of the sample project you sent to demonstrate. I hope this helps you.
XamDataChartNoiseDataDemo - Kopie (2).zip
I was able to reduce my project to a minimum solution to see the problem. I've attached it:
XamDataChartNoiseDataDemo_MyView.zip
I appreciate your help.