Hi,
I am having a chart in my UI. I am adding a series to the chart and then assign the DataSource to the series. Chart takes lots of time to render the chart.
int[] zi = new int[356]; Infragistics.Silverlight.Chart.Series s3 = new Infragistics.Silverlight.Chart.Series(); s3.ChartType = ChartType.Line; for (int j = 0; j < 356; j++) { zi[j] = j; } igChart3.Series.Add(s3); igChart3.Series[0].DataSource = zi;
Alternatively, if I assign data to the series and then add the series to chart, it works perfectly(much quicker).
int[] zi = new int[356]; Infragistics.Silverlight.Chart.Series s3 = new Infragistics.Silverlight.Chart.Series(); s3.ChartType = ChartType.Line; for (int j = 0; j < 356; j++) { zi[j] = j; } s3.DataSource = zi; igChart1.Series.Add(s3);
Why is this performance difference?
Due to this limitation we are not able to do data binding to the series from XAML code.
Regards,
Madhan
Madhan,
please see the documentation for the RefreshEnabled property of the XamWebChart. The crux of the matter is that if your DataSource implements INotifyCollectionChanged, then everytime you make a change to its contents the chart will rerender to accomodate the change you made. This is a good thing, in general, because you want changes to the data source to be respected in the rendering of the chart.
You don't see the performance problem if you add the data to the collection before adding the series to the chart because the chart has special functionality for when it knows a large amount of data is being added at once, and will disable refreshes while the changes are made. You would see the same functionality if you added all the items to your collection and then made it the data source of the series.
If you want to tell the chart that you are making a lot of changes and you only want it to refresh once, at the end, then you can do this:
igChart3.RefreshEnabled = false; //update the data igChart3.RefreshEnabled = true;
Ah, actually, I just noticed you are using an array, which version of the chart are you using?
-Graham
Graham,
I am able to see minor performance improvement with the above approach(tried with the same sample code as above). Need to use this approach in my evaluation application and get back to you.
I am facing another issue in evaluation application as well as in sample code above related to memory.
If you keep on clicking populate button for 40 to 50 times over a period of time. it can be in 30 mins or with in possible quickest time. Memory of the IE will keep on increasing. It will reach 1500 MB and finally IE will crash. We are facing the same scenario in our evaluation application and also in the actual application prototype.
Can you check on this behavior?
Could you describe what happens each time you populate the data source? Some pseudocode, or better a sample? Its possible you are leaking event listeners, or the chart may be, as this version does not use a weak event listener pattern. There are definitely some usage scenarios to avoid with this style of control due to the way they need to listen for data updates. But if you can provide some details on your usage we can track down what is occurring.
I have the same problem of memory leak. to reproduce it, it's easy:
Create a simple chart in xaml:
<Grid x:Name="LayoutRoot" Background="White"> <Border Height="Auto" Width="Auto" VerticalAlignment="Top" BorderThickness="1,1,1,1" BorderBrush="White" Margin="0,10,0,0"> <StackPanel Height="Auto" Width="250" Margin="0,0,0,0"> <Canvas x:Name="ChartCanvas0" Width="334" Height="368" HorizontalAlignment="Center">
<Chart:XamWebChart x:Name="ChartControl0" Height="364" Width="366" BorderThickness="0" Canvas.Left="-24" Canvas.Top="5"> <Chart:XamWebChart.Legend> <Chart:Legend Visibility="Collapsed"/> </Chart:XamWebChart.Legend> </Chart:XamWebChart> </Canvas> </StackPanel> </Border> </Grid>
In the "code - behing", create a timer who update the seriescollection each 5s:
private void RefreshData(){ IsRefreshable = false; Curves = GetData(); IsRefreshable = true;}
//it's just an example
private SeriesCollection GetData() { SeriesCollection sColl = new SeriesCollection();
for (int i = 0; i < 7; i++) { Series s = new Series(); s.ChartType = ChartType.ScatterLine; ObservableCollection<DataPoint> lData = new ObservableCollection<DataPoint>(); for (int j = 0; j < 200; j++) { DataPoint d = new DataPoint(); d.ChartParameters.Add(new ChartParameter { Type = ChartParameterType.ValueY, Value = i
}); d.ChartParameters.Add(new ChartParameter { Type = ChartParameterType.ValueX, Value = j
}); lData.Add(d); } s.DataPoints = lData; sColl.Add(s); } return sColl; }
If you check your perfmon or taskmgr, you can see that the memory of the process iexplorer increase for each time you are updating the series of the chart. After some times, an "Outofmemory exception" is throwed by the application.
if you changing the code by just only updated the datapoint or chartparameter, it's the same result.
or, if you binding the seriescollection(MVVM), same result.
The garbageCollector never cleans the old objects.
Have you got an answer for this problem?
Thank you for your quick answer.
Thanks for providing more info. I'll see if I can replicate the issue.
Sorry for the late reply. You can reproduce the memory issue using sample code which was provided by your team in this posting.
Steve,
You may want to try the 10.2 trial. I think you'll find the performance of the new XamDataChart is much better for these kinds of volumes using scatter charts.
Better yet though, with the XamDataChart, you can get even better performance if you use a line series and the CategoryDateTimeXAxis (which supports irregular spacing). The following emulates the situation you describe and returns very speedily. There are some complexities to make the various x axes align, so see my comments interspersed. These concessions aren't needed for the scatter charts, but unfortunately they aren't as zippy as this solution in the current release:
public partial class MainPage : UserControl { List<LineSeries> series = new List<LineSeries>(); public MainPage() { InitializeComponent(); NumericYAxis yAxis = new NumericYAxis(); theChart.Axes.Add(yAxis); List<List<LineData>> datas = new List<List<LineData>>(); for (int k = 0; k < 10; k++) { series.Add(new LineSeries() { //we will plot Double.Nan at the end to //make the axes align, but don't actually show //the value. UnknownValuePlotting = UnknownValuePlotting.DontPlot }); datas.Add(new List<LineData>(30000)); } Random rand = new Random(); DateTime maxX = DateTime.Now.AddYears(-100); List<CategoryDateTimeXAxis> axes = new List<CategoryDateTimeXAxis>(); //generating some sample data. for (int j = 0; j < series.Count; j++) { CategoryDateTimeXAxis xAxis = new CategoryDateTimeXAxis(); xAxis.DateTimeMemberPath = "XValue"; xAxis.Label = "{XVAlue:d}"; axes.Add(xAxis); //need to use a different category xaxis //because the x values are different //but the min/max are aligned //so only need to display one of them if (j != 0) { xAxis.Stroke = new SolidColorBrush(Colors.Transparent); xAxis.LabelSettings = new AxisLabelSettings() { Visibility = Visibility.Collapsed }; } DateTime currentDate = DateTime.Now.AddYears(-100); double currentValue = 100; for (int i = 0; i < 30000; i++) { if (currentDate > maxX) { maxX = currentDate; } datas[j].Add(new LineData() { XValue = currentDate, YValue = currentValue }); if (rand.NextDouble() > .5 ) { currentValue += 5 * rand.NextDouble(); } else { currentValue += -5*rand.NextDouble(); } currentDate = currentDate.AddDays(3 + (-2 + (4 * rand.NextDouble()))); } series[j].XAxis = xAxis; series[j].YAxis = yAxis; series[j].ValueMemberPath = "YValue"; } for (int j = 0; j < series.Count; j++) { //force the x axes to align by plotting an non-plotted //end point for each series at the max x for all series. if (datas[j][datas[j].Count - 1].XValue < maxX) { datas[j].Add(new LineData() { XValue = maxX, YValue = double.NaN }); } series[j].ItemsSource = datas[j]; axes[j].ItemsSource = datas[j]; theChart.Axes.Add(axes[j]); } for (int j = 0; j < series.Count; j++) { theChart.Series.Add(series[j]); } } } public class LineData { public DateTime XValue { get; set; } public double YValue { get; set; } }
Let me know if you have any questions. Hope this helps!-Graham
Hello,
I'm trying to find a silverlight chart that is capable of holding up to 10 time series, each about 30,000 points. I'm plotting them as a scatter plot because the times are irregularly spaced. I just downloaded the trial 2010.1 version and while the chart looks great, it's taking a while to load with just one series of 30,000 points - about 60 secs. I've tried:
1. Create a list of key value pairs and bind that to the series as the data source
2. add the points in a loop one by one as datapoints
3. adjusting the unit of the x axis manually
4. adjusting the label visibility of the x axis manually.
None of these had an impact on the load time.
Is there something I'm missing, or is this the expected performance.
Thanks for any help.
-Steve
I'm going to assume this is the same question as in this post: https://ko.infragistics.com/community/forums/f/retired-products-and-controls/41956/xamwebchart-line-chart-tooltipdate-value-and-performance-issue
Please correct me if this is separate.
There are additional XamWebChart performance improvements that should be available in the next services releases and product release. If you could provide me some sort of sample project I could evaluate if these apply for you, or whether we can examine other improvement options.
We were using 9.1 and after shifting to 10.1 we have clear perfomrnace gains, and chart load time has change to 3 to 4 seconds from appox 15 seconds. Is there still any progress in this context?
Thanks
Hi Graham,
We are also facing same issue, can you tell me in which release this solution will be available.
We are doing data point adding as following: where series are of Line Type and has been definded in xaml
this.cht.RefreshEnabled = false;Series s1 = this.chtValuationMuliple.Series[0];Series s2 = this.chtValuationMuliple.Series[1];
DataPoint dp;for (int i = 0; i < MyCount; i++){ dp = new DataPoint(val1, date); s1.DataPoints.Add(dp);
dp = new DataPoint(val2); s2.DataPoints.Add(dp);}
this.cht.RefreshEnabled = true;
My application stucks for about 15 seconds on this.cht.RefreshEnabled = true;
Can you please suggest me some work around?