Slow replot of a Qwt graph in embedded linux

2019-08-16 07:32发布

I'm facing some problems while developing an Qt-based embedded solution for Linux. Basically my application plots a QwtPlot graph with up to 8 QwtPlotCurves attached to it. A QwtPlot::replot() is called each 1 second. Data arrives from a socket connection connected to another .c app in the same system. Hardware is a Texas' OMAP.

The problem is that depending on the configuration, the replot becomes very, very slow. To be more specific, if I put 4 curves to be shown, no delay is perceived, but if I attach the 8 curves, then a lag/dealy of 400-500 ms starts appearing.

I started debugging the system to find where the bottleneck could be (there are 3 stages: the first receives the points and guard them inside a temporary buffer with little processing in-between, the second copies those points into the plot points vectors and the third is like a timer that calls QwtPlot::replot() to update the graph) and after discarding the two first stages, I though that the real problem was surrouding the replot() method: I'ld expect that, starting a timer before calling it and calling QTime::elapsed() to seem how much time it was taken, I'ld find a big number.

But wrong! The method only takes 10-15 ms compared to the 400-500 ms of delay that I'm facing. With this in mind, I came with the question: does QwtPlot::replot() calls something to happen and then move on after it, so while I computed 10 ms my application is actually running lots of code, or should I conclude that this immense time required to do the replotting is a hardware's fault who is not being capable of handling the job appropriately?

Btw., using OpenGL (Qwt offers such possibility) could solve my problem? Wouldn't it have some drawback of killing processor for the other tasks?

EDIT:

  • Obs. 1: Regarding OpenGL, I already learned (in another question here in SO) that I'll not be capable of using it for the specific embedded situation I have now since my processor doesn't have a GPU and any other way of using OpenGL wouldn't be actually helpful (see this link for details).
  • Obs. 2: The replot refresh is done once per second, so the problem certainly doesn't come from excessive replot calls, and using partial reploting (by means of QwtPlotDirectPainter or similar) is fruitless.
  • Obs. 3: By now I reimplemented the QwtPlot::replot() method so it only calls 3 methods now:

    updateAxes();
    
    poCanvas->invalidateBackingStore();
    poCanvas->update();
    

1条回答
放我归山
2楼-- · 2019-08-16 08:11

I do real time plotting with 30+ data same time, with their fft operations, onto 2 different plots, without such delay. I had my observations; if you are working with real-time data, you can get some ideas:

Try to delete stale curve data -clear everything but last 10 sec for instance- before replot.

Since you always write to future, try to call replot only when the plot needs to be shifted, not at every update.

Try to utilize QwtPlotDirectPainter.

Try to utilize canvas and painter attributes.

Try to change your receiving method smt like using a timer to check the socket, instead of firing a slot for every received byte.

Always try to move your timers to seperate threads.

EDIT: Lets talk about actual answers now -I've read through your question too fast, sorry:

Replot takes 10ms, but "queued" replots seems to be your main problem, you are probably firing too many replots (like every milisecond), and your thread may be queueing those events.

OpenGL enabled QwtPlotGLCanvas introduced in qwt 6.1 and you can test it from refreshtest example under your qwt root folder. From that you can compare GPU+CPU with CPU only.

There is also an oscilloscope example from what you can see how direct painter works, how to utilize it instead of slow replotting, and even with CPU rendering you can get efficient updates to your plots.

查看更多
登录 后发表回答