PDA

View Full Version : slow signal-slot-mechanism



blm
27th October 2008, 13:59
hallo everbody,

in my multi thread program, i used signal-slot connections across threads, but i find this is not a good idea--because it`s too slow..

I have heard that the reaction time of the signal-slot-mechanism is just 110ms!?:confused:

but my realtime system asks for max. 10ms!!

now how can I do that!?

gri
27th October 2008, 14:09
What type of data do you send over signal/slot? Implicit sharing does not work across threads, so QList<>'s etc. are copied.
Also it matters how frequently you send data since it's handled over event loops.

blm
27th October 2008, 14:27
What type of data do you send over signal/slot? Implicit sharing does not work across threads, so QList<>'s etc. are copied.
Also it matters how frequently you send data since it's handled over event loops.

thanks, gri.

in workerthread will be in every 10ms a data acquisition process, the type of data to send is QpointF.

in my main thread was written like this:


connect(workerthread, SIGNAL(newDataCome(const QPointF&)), this, SLOT(paintNewPoint(const QPointF&)));


the program works, but just only slowly..

gri
27th October 2008, 14:33
I think that's your problem. That a signal every 10 ms is too frequently...
I assume you send some data from the worker thread to the gui? If you really need to have the data every 10 ms, you should not use signals and slots for this. Otherwise, if you only need the data you should bundle the points together and send less signals with the same information. Painting the gui also takes cpu so updating it too frequently slows down everything.

blm
27th October 2008, 14:55
I think that's your problem. That a signal every 10 ms is too frequently...
I assume you send some data from the worker thread to the gui? If you really need to have the data every 10 ms, you should not use signals and slots for this. Otherwise, if you only need the data you should bundle the points together and send less signals with the same information. Painting the gui also takes cpu so updating it too frequently slows down everything.

thanks for your tip, yes, I send data from the worker thread to the gui, but except the signals and slots, which function can I use under such frequence?

gri
27th October 2008, 15:39
You could change the data directly, but with locking!

For example:
Your thread class has a QList<QPointF> which contains all points, old ones and generated ones. The gui polls for data using a QReadLocker every 40 - 50 ms (less frequent is better), the the worker thread puts new points in with the QWriteLocker.

The other way round would also work:
The gui thread holds the data and the worker thread notifies a class directly that there are new points, locking is also necessary here.

So: Signal/Slot is a good solution for multithreading if you don't want the data fast but have a very simple and stable code without knowing much about threading. Locking is more complicated and can also lead to slow code, if you lock too often....

blm
27th October 2008, 16:10
The other way round would also work:
The gui thread holds the data and the worker thread notifies a class directly that there are new points, locking is also necessary here.

Question:
How can the worker thread notifies the gui thread that new data comes but without signal-slot?? Danke!:o
I use Signal-slot because it can easily generate a "message"..

gri
27th October 2008, 16:28
Question:
How can the worker thread notifies the gui thread that new data comes but without signal-slot?? Danke!:o
I use Signal-slot because it can easily generate a "message"..

You can notify the gui with a direct function call or an direct interface call to be more abstract. However, you need to use QReadLocker and QWriteLocker then to ensure that no one writes in the memory where the other thread reads from at the same time.

The simple solution (without locking) would be to bundle the points you're sending. Updating the gui every 10 ms is not very efficient. So bundling the data together and sending each 100 ms a QList<QPointF> over signal/slot would be much faster. Your eyes can't see the difference between 10 ms and 100 ms, if you're not gaming ;) Painting should happen as less as possible..

wysota
28th October 2008, 01:09
Are you using a real-time OS? Because if not then whatever you do, you will not force the 10ms barrier simply because your OS doesn't guarantee response times. Signal-slot connection is a simple function call when it's done in a single thread, so the overhead is minimal (actually it expands to about 10 lines of code). If you send a signal across threads, the data needs to be serialized (which can be quite quick if you pass a minimum quantity of data) and then an event is posted to the receiving thread which takes a bit longer but that's only part of the work that needs to be done. Now the problem is there are no guarantees (or even insights) when that other thread will get a chance to process the event. First of all it has to obtain the processor (which is totally up to the OS) and then it had to return to the event loop to process the signal. So the real delay depends on the system you are running on and its load and on the nature of the receving thread. I don't know where did you come up with the "110ms" value, but it's totally bogus. And using other mechanisms including synchronizing won't help. The latter will even make things worse.

Anyway, I think your problem is different. I think the problem is not the delay before the signal gets processed but rather your thinking that you indeed require a delay less than 10ms. What will happen if you get a 11ms delay? Something will explode or you'll simply see the effects 1ms later than you expect? The hand is quicker than the eye and that's probably because your eyes are quite slow. You only need several frames per second to cheat it to think it is looking at a moving object. So if it's only about display, you can surely cope with much greater delays. If you think you want such little delays because need to store some data with a particular timestamp, simply attach the timestamp before sending the signal - I'm sure nobody will mind if the actual data arrives a few miliseconds later if it is accounted correctly. Generally speaking - where did you get this "10ms" from?

blm
28th October 2008, 11:19
thank you, wysota,

I´sorry I think there is a mistake--"my realtime system" means my hardware device , a measurement system. Actually my multithread software runs under Windows XP.

in every 10ms the device got a data and send it to PC via RS-232. The Workerthread will receive the data and post it to GUI.

In fact i have wrote a simulation program, the workerthread read data form a local file, und i set a QThread::msleep(10) between twice reading.
I hope my gui thread can paint a new point in every 10ms too, but it seems distinctly slower as i purposed.

Brandybuck
28th October 2008, 17:22
A quick tip: If all you want to do every 10ms is to draw a new point on a graph (or some similar gui display), then draw to a QImage instead. A QImage is not a gui object, so your worker thread can paint to it. Then in main thread run a timer that calls update() at the update frequency you want. A quarter to half second should be fine for most purposes. In the repaint, just draw the qimage. Or you could do the same thing with an array of points, etc.

wysota
28th October 2008, 18:10
thank you, wysota,

I´sorry I think there is a mistake--"my realtime system" means my hardware device , a measurement system. Actually my multithread software runs under Windows XP.

in every 10ms the device got a data and send it to PC via RS-232. The Workerthread will receive the data and post it to GUI.

In fact i have wrote a simulation program, the workerthread read data form a local file, und i set a QThread::msleep(10) between twice reading.
I hope my gui thread can paint a new point in every 10ms too, but it seems distinctly slower as i purposed.
I suggest you group data and add it to the drawing only a few times per second. A quarter of a second as David suggested seems fine. If you want more fluency, you can make that 10 times per second.