Reputation: 464
I plot animated graph with Dynamic Data Display - graph that has source with constantly adding new points (about 10 times per second and 10 points per time). The problem is the performance degrade if these points form line segments which are big in compare to plotter size. In other words I can add thousands of points but if they forms comparably small line segments the performance will be good. But if I add only few hundreds points which form big line segments (they occupy all the plotter's area) the performance will be very poor.
The following images illustrate the problem. The first image is just hundreds line segments and performance is very poor on my machine. In the second image I just add two points to make the rest points took small place on the plotter due to plotter's scaling.
It doesn't matter how fast your machine is (mine is Pentium G3220 with integrated GPU, 16 GB RAM, and another one is relatively same CPU with discrete GeForce 640 GT) - I can add much more points and will fall your machine down. The behavior will be the same - if I add two "defend scaling" points and make the line segments relatively small on the plotter the performance will be much better.
The following code - how I get such pictures. Leave the adding of two points in MainWindow() commented to obtain the first picture, and uncomment it to obtain the second one. This is just a plane WPF application with all code in one file - in MainWindow's "code behind":
public partial class MainWindow : Window
{
readonly DispatcherTimer _timer = new DispatcherTimer();
int _counter = 0;
int _batchSize= 10;
RingArray<Point> _data = new RingArray<Point>(2000);
EnumerableDataSource<Point> _ds;
public MainWindow()
{
InitializeComponent();
_ds = new EnumerableDataSource<Point>(_data);
_ds.SetXMapping(d => d.X);
_ds.SetYMapping(d => d.Y);
LineGraph chart = plotter.AddLineGraph(_ds, Colors.Blue, 2.0);
//_data.Add(
// new Point
// {
// X = -1,
// Y = 200
// });
//_data.Add(
// new Point
// {
// X = -0.5,
// Y = -200
// });
_timer.Tick += OnTimerTick;
_timer.Interval = TimeSpan.FromMilliseconds(100);
_timer.Start();
}
void OnTimerTick(object sender, EventArgs e)
{
_data.AddMany(
Enumerable.Range(0, _batchSize)
.Select(v =>
{
// I don't use the "v" here - the "_counter" is enough.
var p = new Point
{
X = (double)_counter,
Y = (double)(_counter % 2 == 0 ? 0 : 1)
};
_counter++;
return p;
}));
}
}
public class Point
{
public double X { get; set; }
public double Y { get; set; }
}
It doesn't matter whether I use EnumerableDataSource or ObservableDataSource with AppendAsync, Add or AddMany - it is all the same behavior: the performance depends only on the size of line segments relatively to screen size (or plotter size). The problem lays definitely in the field of 1) WPF's rendering system, and 2) rasterization.
1) bad WPF's rendering system https://jeremiahmorrill.wordpress.com/2011/02/14/a-critical-deep-dive-into-the-wpf-rendering-system/
2) rasterization - the more pixels the line segments occupy on the screen the less performance will be... but dude, several hundreds lines fall down my machine but Crysis on max settings not! Ridiculous!
I know the following approaches to cope with this problem:
What else would you offer?
Upvotes: 1
Views: 411