mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-25 01:51:49 +08:00
added speed-test
This commit is contained in:
parent
4680106734
commit
6520e598a9
@ -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
|
||||
|
@ -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 |
|
||||
|
BIN
screenshots/contextmenu_graph_visibility.png
Normal file
BIN
screenshots/contextmenu_graph_visibility.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
BIN
screenshots/jkqtplotter_simpletest_speed.png
Normal file
BIN
screenshots/jkqtplotter_simpletest_speed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
screenshots/jkqtplotter_simpletest_speed_small.png
Normal file
BIN
screenshots/jkqtplotter_simpletest_speed_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
87
test/jkqtplotter_simpletest_speed/README.md
Normal file
87
test/jkqtplotter_simpletest_speed/README.md
Normal 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/)
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
97
test/jkqtplotter_simpletest_speed/speedtestplot.cpp
Normal file
97
test/jkqtplotter_simpletest_speed/speedtestplot.cpp
Normal 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()));
|
||||
}
|
22
test/jkqtplotter_simpletest_speed/speedtestplot.h
Normal file
22
test/jkqtplotter_simpletest_speed/speedtestplot.h
Normal 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();
|
||||
};
|
Loading…
Reference in New Issue
Block a user