added speed-test

This commit is contained in:
jkriege2 2018-12-02 18:30:29 +01:00
parent 4680106734
commit 6520e598a9
11 changed files with 258 additions and 1 deletions

View File

@ -12,6 +12,7 @@ SUBDIRS += jkqtplotterlib \
jkqtplotter_simpletest_dateaxes \
jkqtplotter_simpletest_barchart \
jkqtplotter_simpletest \
jkqtplotter_simpletest_speed \
jkqtplot_test
#jkqtplotter_simpletest_imageplot_nodatastore \
#jkqtplotter_simpletest_rgbimageplot_opencv \
@ -68,3 +69,6 @@ jkqtplotter_simpletest_symbols_and_errors.depends = jkqtplotterlib
jkqtplotter_simpletest_symbols_and_styles.subdir = test/jkqtplotter_simpletest_symbols_and_styles
jkqtplotter_simpletest_symbols_and_styles.depends = jkqtplotterlib
jkqtplotter_simpletest_speed.subdir = test/jkqtplotter_simpletest_speed
jkqtplotter_simpletest_speed.depends = jkqtplotterlib

View File

@ -17,7 +17,8 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
| Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest1_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest) | [Very Basic Example (Line Graph)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest) | `JKQTPxyLineGraph`<br/>C-style arrays of data |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest1_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest) | [Very Basic Example (Line Graph)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest) | `JKQTPxyLineGraph`<br/>C++-style QVector arrays of data |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_speed_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_speed) | [Line Graph with Live Data / Speed Test](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_speed) | `JKQTPxyLineGraph`<br/>external C-style arrays of data, not owned by datastore<br/>live-data |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_symbols_and_styles_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_symbols_and_styles) | [Line Graph with Different Symbols and Line Styles](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_symbols_and_styles) | `JKQTPxyLineGraph`<br/>C++ vector of data<br/>setting line styles and symbol styles<br/>automatic graph coloring |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_symbols_and_errors_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_symbols_and_errors) | [Simple Line/Symbol Graph With Errorbars](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_symbols_and_errors) | `JKQTPxyLineErrorGraph`<br/>C-style arrays of data |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_errorbarstyles_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_errorbarstyles) | [Different Types of Errorindicators](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_errorbarstyles) | `JKQTPxyLineErrorGraph`<br/>different styles of error indicators for x- and y-errors<br>C++-style QVector for data<br/>styling error indicators<br/>moving key and formatting plotter grid |

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,87 @@
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)
# JKQtPlotter
## Simple line-graph with live-data (speed test)
This project (see `./test/jkqtplotter_simpletest_speed/`) simply creates a JKQtPlotter widget (as a new window) and adds two line-graph (a sine and a cosine wave).
Data is stored in two [`std::array<double, NDATA>`](https://en.cppreference.com/w/cpp/container/array) objects (`X`, `Y`, and `Y2`) and the data is added as external pointer to the datastore:
```c++
// 3. make data available to JKQtPlotter by adding it to the internal datastore.
// Here the data from the std::array's is not copied, but only the pointer to
// the array is added to the datastore. therefore the datastore does not manage
// the memory, oly uses the data stored in it!
JKQTPdatastore* ds=getDatastore();
size_t columnX=ds->addColumn(X.data(), X.size(), "x");
size_t columnY=ds->addColumn(Y.data(), Y.size(), "y");
size_t columnY2=ds->addColumn(Y2.data(), Y2.size(), "y2");
```
The datastore then uses the data from the `std::array` instances, but does not own their memory, i.e. also does not free it. This is useful, when data fro external sources should be used without copying.
For this example we also don't use axis autoscaling, but set the axes explicitly:
```c++
// 6. scale the plot so the graph is contained
setX(X[0], X[NDATA-1]);
setY(-2,2);
```
Finally a slot is started with a one-shot timer. In that slot, the data is shifted one place to the left and the graph is updated. The slot also calculated the current framerate and displays it in the window title. Finally a single-shot timer with 1ms delay is used to call the slot again (i.e. continuously):
```c++
void SpeedTestPlot::plotNewData()
{
// move old data to the left
for (size_t i=0; i<NDATA-1; i++) {
X[i]=X[i+1];
Y[i]=Y[i+1];
Y2[i]=Y2[i+1];
}
// add one new data point
X[NDATA-1]=X[NDATA-2]+dx;
Y[NDATA-1]=sin(X[NDATA-1])+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
Y2[NDATA-1]=cos(X[NDATA-1])+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
// set new x-range and replot
setX(X[0], X[NDATA-1]);
update_plot();
// calculate and update FPS-rate in window title
auto tlastalst=t_lastplot;
t_lastplot=std::chrono::system_clock::now();
double delta_secs=static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(t_lastplot-tlastalst).count())/1000.0;
setWindowTitle(QString("Live Data Speed Test: %2 datapoint, %1 fps").arg(1/delta_secs).arg(NDATA));
// enqueue call for next data value
QTimer::singleShot(1, this, SLOT(plotNewData()));
}
```
The result looks like this:
![jkqtplotter_simpletest_speed1](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_speed.png)
There are different facor affecting the replot speed:
1. *Anti-Aliasing:* If `JKQtPlotter` uses Anti-Aliasing for plotting, the plots are much nicer, but also about a factor of 3-4 slower. This is due to the increased amount of calculations, necessary in the drawing sub-system of Qt.
You can configrue anti-aliasing with these calls:
```c++
plot.get_plotter()->set_useAntiAliasingForGraphs(false);
plot.get_plotter()->set_useAntiAliasingForSystem(false);
plot.get_plotter()->set_useAntiAliasingForText(false);
```
2. *Number of Graphs:* The number of plots (and also ther type and complexity) is a major imapct factor in the plotting speed. You can switch off a plot with the context menu:<br>![contextmenu_graph_visibility](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/contextmenu_graph_visibility.png)
3. *Axis Scales and Plot Appearance:* Replotting is done in two steps: First the plot with the axes, labels etc. is drawn. Then the graphs are draw on top. Therefore a replot is faster, if only the graphs change, because the background (plot) does not have to be replotted.
the next table summarizes some results for plotting speed under different conditions, obatined with the test program in this directory (conditions: Qt 5.11, 32-bit, MinGW, Release, Phenom II X4 765, 500 data points):
| Anti-Aliasing | X-Axis Redraw | # Graphs | frame rate [fps] |
| ---------------- | --------------- | ------------- | ---------------- |
| yes | yes | 2 | 4 |
| yes | yes | 1 | 7 |
| yes | no | 2 | 9 |
| yes | no | 1 | 16 |
| no | yes | 2 | 18 |
| no | yes | 1 | 24 |
| no | no | 2 | 32 |
| no | no | 1 | 48 |
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)

View File

@ -0,0 +1,17 @@
#include <QApplication>
#include <array>
#include <random>
#include "jkqtplotter/jkqtplotter.h"
#include "speedtestplot.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
SpeedTestPlot plot;
QTimer::singleShot(500, &plot, SLOT(plotNewData()));
return app.exec();
}

View File

@ -0,0 +1,21 @@
# source code for this simple demo
SOURCES = jkqtplotter_simpletest_speed.cpp speedtestplot.cpp
HEADERS = speedtestplot.h
# configure Qt
CONFIG += qt
QT += core gui xml svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
# output executable name
TARGET = jkqtplotter_simpletest_speed
# include JKQtPlotter source code
DEPENDPATH += . ../../lib
INCLUDEPATH += ../../lib
CONFIG (debug, debug|release):LIBS += -L../../lib/debug -ljkqtplotterlib
CONFIG (release):LIBS += -L../../lib/release -ljkqtplotterlib
# here you can activate some debug options
#DEFINES += SHOW_JKQTPLOTTER_DEBUG
#DEFINES += JKQTBP_AUTOTIMER

View File

@ -0,0 +1,8 @@
TEMPLATE = subdirs
SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_speed
jkqtplotterlib.file = ../../lib/jkqtplotterlib.pro
jkqtplotter_simpletest_speed.file=$$PWD/jkqtplotter_simpletest_speed.pro
jkqtplotter_simpletest_speed.depends = jkqtplotterlib

View File

@ -0,0 +1,97 @@
#include "speedtestplot.h"
SpeedTestPlot::SpeedTestPlot():
JKQtPlotter(), dx(1.0/double(NDATA)*4.0*M_PI), x0(0)
{
// 1. optimize JKQtPlotter for speed (by switching off anti-aliasing)
get_plotter()->set_useAntiAliasingForGraphs(false);
get_plotter()->set_useAntiAliasingForSystem(false);
get_plotter()->set_useAntiAliasingForText(false);
// 2. now we create data for a simple plot (a sine curve + random[-0.5,0.5])
for (size_t i=0; i<NDATA; i++) {
const double x=static_cast<double>(i)*dx;
X[i]=x0+x;
Y[i]=sin(x)+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
Y2[i]=cos(x)+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
}
// 3. make data available to JKQtPlotter by adding it to the internal datastore.
// Here the data from the std::array's is not copied, but only the pointer to
// the array is added to the datastore. therefore the datastore does not manage
// the memory, oly uses the data stored in it!
JKQTPdatastore* ds=getDatastore();
size_t columnX=ds->addColumn(X.data(), X.size(), "x");
size_t columnY=ds->addColumn(Y.data(), Y.size(), "y");
size_t columnY2=ds->addColumn(Y2.data(), Y2.size(), "y2");
// 4. create two graphs in the plot, which plots the dataset X/Y:
JKQTPxyLineGraph* graph=new JKQTPxyLineGraph(this);
graph->set_xColumn(columnX);
graph->set_yColumn(columnY);
graph->set_title(QObject::tr("live sin() graph"));
graph->set_lineWidth(1);
addGraph(graph);
JKQTPxyLineGraph* graph2=new JKQTPxyLineGraph(this);
graph2->set_xColumn(columnX);
graph2->set_yColumn(columnY2);
graph2->set_title(QObject::tr("live cos() graph"));
graph2->set_lineWidth(1);
addGraph(graph2);
// 6. scale the plot so the graph is contained
setX(X[0], X[NDATA-1]);
setY(-2,2);
// show plotter and make it a decent size
show();
resize(1000,500);
}
SpeedTestPlot::~SpeedTestPlot()
{
}
void SpeedTestPlot::plotNewData()
{
// move old data to the left
for (size_t i=0; i<NDATA-1; i++) {
X[i]=X[i+1];
Y[i]=Y[i+1];
Y2[i]=Y2[i+1];
}
// add one new data point
X[NDATA-1]=X[NDATA-2]+dx;
Y[NDATA-1]=sin(X[NDATA-1])+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
Y2[NDATA-1]=cos(X[NDATA-1])+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
/*
// ALTERNATIVE: MOVE data, but keep x-axis range
x0+=dx;
for (size_t i=0; i<NDATA-1; i++) {
Y[i]=Y[i+1];
Y2[i]=Y2[i+1];
}
// add one new data point
Y[NDATA-1]=sin(X[NDATA-1]+x0)+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
Y2[NDATA-1]=cos(X[NDATA-1]+x0)+static_cast<double>(std::rand())/static_cast<double>(RAND_MAX + 1u)-0.5;
*/
// set new x-range and replot
setX(X[0], X[NDATA-1]);
update_plot();
// calculate and update FPS-rate in window title
auto tlastalst=t_lastplot;
t_lastplot=std::chrono::system_clock::now();
double delta_secs=static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(t_lastplot-tlastalst).count())/1000.0;
setWindowTitle(QString("Live Data Speed Test: %2 datapoint, %1 fps").arg(1/delta_secs).arg(NDATA));
// enqueue call for next data value
QTimer::singleShot(1, this, SLOT(plotNewData()));
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <array>
#include <random>
#include "jkqtplotter/jkqtplotter.h"
#define NDATA 500
class SpeedTestPlot: public JKQtPlotter {
Q_OBJECT
protected:
std::array<double, NDATA> X, Y, Y2;
const double dx;
double x0;
std::chrono::system_clock::time_point t_lastplot;
public:
SpeedTestPlot();
virtual ~SpeedTestPlot();
public slots:
void plotNewData();
};