PDA

View Full Version : DIscard old signals



quimnuss
14th September 2015, 11:28
On a single-processor machine, I have a QSerial publishing data at 1Hz, whose signal is then processed and another signal is emitted to notify the GUI which updates the display.

On slow computers, the subsequent graphical display and computation might be sometimes slower than 1Hz, causing the signals to pile up and therefore the application display is dramatically delayed. I would like to skip "frames" when this happens, therefore ignoring the old signals and handling only the last one.

Right now I am trying to do a manual skip if I detect that fps is lower than 1Hz, but is there a way to discard/ignore the old signals when entering the slot?

The signal doesn't have any arguments, I just use it as signaling there's new input. So one might think that the data would always be the newest one anyway, even if unnecessarly displayed twice. But, the fact that the display displays old data is probably caused because the new signals from the QSerial aren't treated until the display slot is done, therefore the data is always the one the signal was sent for instead of the newest possible, because that serial data hasn't been processed by the middle-man processing object.

Is my reasonment correct?

I've found the function
QCoreApplication::removePostedEvents but what does
killing events may cause receiver to break one or more invariants. mean?

anda_skoa
14th September 2015, 12:42
In a single threaded application, a signal/slot connection is, by default, a direct method call.

Events are only used when Qt::QueuedConnection is used in connect() or, in a multithreaded application, when a signal/slot connection "crosses thread boundaries".

Have you done some profiling where the program spends most of the time?
During processing or during UI updating?

Cheers,
_

quimnuss
14th September 2015, 13:38
UI updating or processing, depending on how you look at it. Most time is spent in the QCustomPlot update (replot) (20%) and the setPixmap (24%) and resize (20%) of a slave window that clones (almost) the full MainWindow (60%).

Maybe I can skip the resize or find a different way of cloning the main window, but I would like to have a failsafe anyway and skip frames if it can't catch up. It's better that than accumulating delay.

Is there a way of telling how many calls of type <type> are there in the queue so I can skip n frames? queue/events or whatever should I call it in a single-threaded application.

[off-topic] I used the trial version of GlowCode to find out, attaching to the Debug version of the application, which goes at half the speed of the release mode. I also tried Very Sleepy but it didn't list the function names and times but its addresses.

I am not so familiar on profiling in windows, so alternatives are very welcome.

anda_skoa
14th September 2015, 13:56
The only "queue" you have is the event queue processing the serial events.

You could QElapsedTimer in the class that receives the QSerial signals.
if the elapsed time is > 1000ms, then store the current sample, reset the timer and return without attempting an UI update.

Unfortunately I don't know about profiling on Windows either.

Cheers,
_

quimnuss
14th September 2015, 13:59
Good idea to place the skip frame on the receiver of the qserial, much cleaner than on the receiver of the signal emitted by it. I have the recurring misconception that the serial event is launched concurrently.

I'll get into the profiling later to speed up the application.

Lesiok
14th September 2015, 16:01
In the slot connected to signal from QSerial only put data in the queue. Draw data in slot connected to the timer and always get only last data from the queue or design an algorithm which data processing.

quimnuss
14th September 2015, 16:07
Hello Lesiok,

The problem with using a timer is that then I would force the program to run at the timer speed instead of going at the serial speed. At least with the skip approach I can go full speed when possible.

Cheers!