Chart ZoomScroll Performance Issue

10 posts, 0 answers
  1. Shawn
    Shawn avatar
    22 posts
    Member since:
    Jul 2011

    Posted 31 Jan 2012 Link to this post

    Hello,

    I'm using a RadChart databound to an ObservableCollection that display three simultaneous lines. The ObservableCollection has points added to it at a rate of approximately 30 per second. This works great except for when I enable the ZoomScroll on the chart.

    When the ZoomScroll (I've only tested the x-axis) is enabled, the application slows and becomes almost unresponsive. However as the application runs and the RadChart gains more and more points the application becomes more responsive.

    I want to know if I'm doing something wrong or if there is some way to fix this issue.

    I have mocked up an app that demonstrates this issue successfully. When you start the app the RadToggleButtons on the left hand side are practically unresponsive but you can get them to work with excessive clicking and a little luck. If you let it run for a while the buttons slowly become more responsive.

    Here is the code:
    XAML:
    <UserControl x:Class="ZoomScrollTestApp.MainPage"
        mc:Ignorable="d"
        xmlns:ZoomScrollTestApp="clr-namespace:ZoomScrollTestApp"
        d:DesignHeight="300" d:DesignWidth="400">
     
        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
     
            <Grid Visibility="Visible" Grid.Column="1">
                <Border x:Name="brdAcceleration">
                    <telerik:RadChart x:Name="chartAcceleration" Tag="Acceleration" Margin="-5 2 0 0" >
                        <telerik:RadChart.DefaultView>
                            <telerik:ChartDefaultView ChartLegendPosition="Top">
                                <telerik:ChartDefaultView.ChartArea>
                                    <telerik:ChartArea LegendName="legendAcceleration" EnableAnimations="False">
                                        <telerik:ChartArea.AxisX>
                                            <telerik:AxisX IsDateTime="True" DefaultLabelFormat="#VAL{HH:mm:ss}" AutoRange="True"/>
                                        </telerik:ChartArea.AxisX>
                                        <telerik:ChartArea.AxisY>
                                            <telerik:AxisY AutoRange="True" />
                                        </telerik:ChartArea.AxisY>
                                        <!--Remove Me!-->
                                        <telerik:ChartArea.ZoomScrollSettingsX>
                                            <telerik:ZoomScrollSettings ScrollMode="ScrollAndZoom" MinZoomRange=".005" />
                                        </telerik:ChartArea.ZoomScrollSettingsX>
                                    </telerik:ChartArea>
                                </telerik:ChartDefaultView.ChartArea>
     
                                <telerik:ChartDefaultView.ChartLegend>
                                    <telerik:ChartLegend x:Name="legendAcceleration" Header="Acceleration Test Chart" />
                                </telerik:ChartDefaultView.ChartLegend>
                                <telerik:ChartDefaultView.ChartTitle>
                                    <telerik:ChartTitle />
                                </telerik:ChartDefaultView.ChartTitle>
                            </telerik:ChartDefaultView>
                        </telerik:RadChart.DefaultView>
     
                        <telerik:RadChart.SeriesMappings>
                            <telerik:SeriesMapping x:Name="seriesAccelerationX" LegendLabel="X">
                                <telerik:SeriesMapping.SeriesDefinition>
                                    <telerik:LineSeriesDefinition ShowItemLabels="False" ShowPointMarks="False"/>
                                </telerik:SeriesMapping.SeriesDefinition>
                                <telerik:ItemMapping FieldName="X" DataPointMember="YValue"/>
                                <telerik:ItemMapping FieldName="Date" DataPointMember="XValue"/>
                            </telerik:SeriesMapping>
                            <telerik:SeriesMapping x:Name="seriesAccelerationY" LegendLabel="Y">
                                <telerik:SeriesMapping.SeriesDefinition>
                                    <telerik:LineSeriesDefinition ShowItemLabels="False" ShowPointMarks="False" />
                                </telerik:SeriesMapping.SeriesDefinition>
                                <telerik:ItemMapping FieldName="Y" DataPointMember="YValue"/>
                                <telerik:ItemMapping FieldName="Date" DataPointMember="XValue"/>
                            </telerik:SeriesMapping>
                            <telerik:SeriesMapping x:Name="seriesAccelerationZ" LegendLabel="Z">
                                <telerik:SeriesMapping.SeriesDefinition>
                                    <telerik:LineSeriesDefinition ShowItemLabels="False" ShowPointMarks="False" />
                                </telerik:SeriesMapping.SeriesDefinition>
                                <telerik:ItemMapping FieldName="Z" DataPointMember="YValue"/>
                                <telerik:ItemMapping FieldName="Date" DataPointMember="XValue"/>
                            </telerik:SeriesMapping>
                        </telerik:RadChart.SeriesMappings>
                    </telerik:RadChart>
                </Border>
            </Grid>
        <Border BorderThickness="1" BorderBrush="#22000000" Background="#66FFFFFF" Grid.Column="0" CornerRadius="6" VerticalAlignment="Top">
            <StackPanel x:Name="spButtons" Orientation="Vertical" Margin="5">
                    <telerik:RadRadioButton x:Name="btn1" Content="btn1" Margin="0 5" IsChecked="True" />
                    <telerik:RadRadioButton x:Name="btn2" Content="btn2" />
                    <telerik:RadRadioButton x:Name="btn3" Content="btn3" Margin="0 5" />
                    <telerik:RadRadioButton x:Name="btn4" Content="btn4" />
            </StackPanel>
        </Border>
        </Grid>
    </UserControl>

    Code Behind:
    using System;
    using System.Linq;
    using System.Windows.Controls;
    using System.Windows.Threading;
    using System.Collections.ObjectModel;
     
    namespace ZoomScrollTestApp
    {
        public partial class MainPage : UserControl
        {
            DispatcherTimer timer = new DispatcherTimer();
            private ObservableCollection<AccelerationChartValue> AccelChartPoints = new ObservableCollection<AccelerationChartValue>();
     
            private double[] SineBuffer = new double[200];
            private double[] SquareBuffer = new double[200];
            private double[] SawBuffer = new double[200];
     
            public MainPage()
            {
                InitializeComponent();
                this.chartAcceleration.ItemsSource = AccelChartPoints;
     
                GenerateSine();
                GenerateSquare();
                GenerateSawtooth();
     
                timer.Interval = TimeSpan.FromMilliseconds(33); // Approx 30 additions per second
                timer.Tick += new EventHandler(AddPoint);
                this.timer.Start();
            }
     
            private void GenerateSine()
            {
                int NumSamples = 200;
                double Frequency = 2;
                double SampleRate = 50;
     
                int SamplesPerWave = (int)(SampleRate / Frequency);
                double RadPerSample = (Math.PI * 2) / (double)SamplesPerWave;
                double SinVal = 0;
     
                for (int i = 0; i < NumSamples; i++)
                {
                    SinVal = Math.Sin(RadPerSample * (double)(i % SamplesPerWave));
                    SineBuffer[i] = (Math.Floor(SinVal * 127) + 128);
                }
            }
     
            private void GenerateSquare()
            {
                int NumSamples = 200;
                double Frequency = 2;
                double SampleRate = 50;
     
                int SamplesPerWave = (int)(SampleRate / (Frequency * 2));
     
                int Value = 127;
                int Counter = 0;
                for (int i = 0; i < NumSamples; i++)
                {
                    if (Counter >= SamplesPerWave)
                    {
                        Counter = 0;
                        Value *= -1;
                    }
                    SquareBuffer[i] = Value + 127;
                    Counter++;
                }
            }
     
            private void GenerateSawtooth()
            {
                int NumSamples = 200;
                double Frequency = 2;
                double SampleRate = 50;
     
                int SamplesPerWave = (int)(SampleRate / Frequency);
     
                int Value = 0;
                int Counter = 0;
                double Delta = 255.0 / (double)SamplesPerWave;
                for (int i = 0; i < NumSamples; i++)
                {
                    if (Counter >= SamplesPerWave)
                    {
                        Counter = 0;
                        Value = 0;
                    }
                    else
                    {
                        Value += (int)Math.Round(Delta, 0);
                        if (Value > 255)
                        {
                            Value = 255;
                        }
                    }
                    SawBuffer[i] = Value;
                    Counter++;
                }
            }
     
            private void AddPoint(object sender, EventArgs args)
            {
                AccelChartPoints.Add(new AccelerationChartValue() { Date = DateTime.Now, X = SineBuffer[AccelChartPoints.Count % 200], Y = SquareBuffer[AccelChartPoints.Count % 200], Z = SawBuffer[AccelChartPoints.Count % 200] });
            }
        }
    }


    AccelerationChartValue.cs:
    using System;
     
    namespace ZoomScrollTestApp
    {
        public class AccelerationChartValue
        {
            public double X { get; set; }
            public double Y { get; set; }
            public double Z { get; set; }
     
            public DateTime Date { get; set; }
        }
    }

    Thanks in advance for you help,
    Shawn
  2. Nikolay
    Admin
    Nikolay avatar
    385 posts

    Posted 03 Feb 2012 Link to this post

    Hello Shawn,

    There are a number of performance tips in this help topic, one of the main being setting manual axes ranges wherever possible in such scenarios, instead of using the autorange.

    In case you are still in the process of selecting the most suitable component, we would highly recommend using our new RadChartView control for live data scenarios like yours, as it is specifically optimized with performance in mind and would handle large data much faster than RadChart. You can find an example of a live data scenario in our demo.

    Regards,
    Nikolay
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
  3. DevCraft banner
  4. Shawn
    Shawn avatar
    22 posts
    Member since:
    Jul 2011

    Posted 09 Feb 2012 Link to this post

    Nikolay,

    Thanks for your response. If I were to change to the RadChartView control for the live data would I preserve the ability to zoom in on a selected data range as I do now? This is necessary for my project.

    Shawn
  5. Nikolay
    Admin
    Nikolay avatar
    385 posts

    Posted 13 Feb 2012 Link to this post

    Hello Shawn,

    Yes, RadChartView supports zooming and scrolling using the ChartPanAndZoomBehavior class. You can find more information on the feature in this help topic.

    All the best,
    Nikolay
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
  6. Shawn
    Shawn avatar
    22 posts
    Member since:
    Jul 2011

    Posted 14 Feb 2012 Link to this post

    Hello again Nikolay,
    Thank you again for your explanation. I have been able to get it working much better with the RadChartView but I ran into an issue. With the RadChart I was able to get and set the RangeEnd, RangeStart, SliderSelectionEnd, and SliderSelectionStart from the ZoomScrollSettings. Is there any way to get and set the equivalent values for the RadChartView?

    Thanks,
    Shawn
  7. Nikolay
    Admin
    Nikolay avatar
    385 posts

    Posted 17 Feb 2012 Link to this post

    Hi Shawn,

    The respective properties are RadCartesianChart.Zoom and RadCartesianChart.PanOffset. Here is a sample snippet that demonstrates this : 
    <telerik:RadCartesianChart x:Name="RadChart1" Width="800" Height="600" Zoom="10,1" PanOffset="-1000,0"/>

    The offset should be provided in negative absolute values. In the above snippet the chart would be offset horizontally at 1000px with a horizontal Zoom level of 10, while not being zoomed vertically. 

    Kind regards,
    Nikolay
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
  8. Shawn
    Shawn avatar
    22 posts
    Member since:
    Jul 2011

    Posted 23 Feb 2012 Link to this post

    Nikolay,
    Thanks again for your help.

    I have another question: I noticed the scroll bar for the RadChartView isn't as pretty as the scroll bar for the RadChart and its functionality is as good either. What I mean is often times when trying to scroll or widen the view the scroll bar loses focus and I end up zooming in on the graph using the selection range. Is there any way to fix this?
  9. Nikolay
    Admin
    Nikolay avatar
    385 posts

    Posted 28 Feb 2012 Link to this post

    Hi Shawn,

    The scroll bar for both chart controls is exactly the same as functionality, it's only the styling that is different - it's more metro for RadChartView. Could you, please, elaborate a bit more on the focusing issue you've encountered as we're not aware of such a problem. We would appreciate any feedback and/or a sample application which demonstrates the issue so that we can test locally.

    Greetings,
    Nikolay
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
  10. Shawn
    Shawn avatar
    22 posts
    Member since:
    Jul 2011

    Posted 29 Feb 2012 Link to this post

    Using the project code I gave previously if you replace the "chartAcceleration" with this code snippet:

    <chart:RadCartesianChart x:Name="cartChartAccel" Grid.Column="1" >
        <chartView:LineSeries CategoryBinding="Date" ValueBinding="X" Stroke="Blue" StrokeThickness="2"/>
        <chartView:LineSeries CategoryBinding="Date" ValueBinding="Y" Stroke="Green" StrokeThickness="2"/>
        <chartView:LineSeries CategoryBinding="Date" ValueBinding="Z" Stroke="Red" StrokeThickness="2"/>
        
        <chart:RadCartesianChart.Behaviors>
            <telerik:ChartPanAndZoomBehavior x:Name="AccelChartZoom" ZoomMode="Horizontal" PanMode="Horizontal"/>
        </chart:RadCartesianChart.Behaviors>
         
        <chart:RadCartesianChart.HorizontalAxis>
            <chartView:DateTimeContinuousAxis MajorStepUnit="Hour"
                                            LabelInterval="5"
                                            LabelFormat="HH:mm:ss.f" FontFamily="Segoe UI"
                                            PlotMode="OnTicks" />
        </chart:RadCartesianChart.HorizontalAxis>
     
        <chart:RadCartesianChart.VerticalAxis>
            <chartView:LinearAxis FontFamily="Segoe UI" />
        </chart:RadCartesianChart.VerticalAxis>
        <chart:RadCartesianChart.Grid>
            <chartView:CartesianChartGrid MajorLinesVisibility="Y" MajorYLineDashArray="3,4" />
        </chart:RadCartesianChart.Grid>
    </chart:RadCartesianChart>
    and replace "this.chartAcceleration.ItemsSource = AccelChartPoints;" with the following snippet in the MainPage constructor:

    cartChartAccel.Series[0].ItemsSource = this.AccelChartPoints;
    cartChartAccel.Series[1].ItemsSource = this.AccelChartPoints;
    cartChartAccel.Series[2].ItemsSource = this.AccelChartPoints;

    Wait for about 30 seconds. and try to use the scroll bar in various ways. When I do this i experience some serious issues with scrolling and zooming.
  11. Ves
    Admin
    Ves avatar
    2879 posts

    Posted 05 Mar 2012 Link to this post

    Hi Shawn,

    Thank you for the additional details. I can confirm that we were able to reproduce the problem. I have logged it in our public issue tracking system -- link -- so you can track it and vote for it. I have updated your Telerik points.

    Best regards,
    Ves
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
Back to Top
DevCraft banner