| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 3 | |
I'm using Qt's signal/slots mechanism for communicating events from a worker thread to the main application. The main application receives these events and updates a related model (which again updates a view). With lots of events from the main application, the GUI of the application appears slow/sluggish (menu selection, popup menus, repaints and similar), probably because the events from the GUI itself is queued in the same queue as the events from the worker thread. Does anybody have any suggestion on what would be a good strategy for making the GUI of the application appear faster (i.e. not slow/sluggish)? Any way to prioritize "normal" GUI events, or turn the priority for signals from the worked thread down? Thanks, Marius K. -- [ signature omitted ]
Am Dienstag, 15. April 2008 schrieb Marius Kjeldahl: > I'm using Qt's signal/slots mechanism for communicating events from a > worker thread to the main application. The main application receives > these events and updates a related model (which again updates a view). > With lots of events from the main application, the GUI of the > application appears slow/sluggish (menu selection, popup menus, repaints > and similar), probably because the events from the GUI itself is queued > in the same queue as the events from the worker thread. > Does anybody have any suggestion on what would be a good strategy for > making the GUI of the application appear faster (i.e. not > slow/sluggish)? Any way to prioritize "normal" GUI events, or turn the > priority for signals from the worked thread down? You should try to compact changes. From my own usage I know that sending around 400 events per second for several hours doesn't slow down qt at all. And here each of these events means a model-update. But if you emit the model-changed event the same number of times, all the views on it have to update and repaint. And there it becomes slow. So it it wise to cache the model-updates and emit the model-changed signal only once a second (for example). That way I can process 400 datasets per second where each dataset gets send through 4 threads via events for hours. I tested this with a 10.000.000 to 1.000.000.000 datasets. (Where each dataset means around 5 events including pushing the final data into a model.) Have fun, Arnold -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
Arnold Krille wrote: > From my own usage I know that sending around 400 events per second for several > hours doesn't slow down qt at all. And here each of these events means a > model-update. But if you emit the model-changed event the same number of > times, all the views on it have to update and repaint. And there it becomes > slow. So it it wise to cache the model-updates and emit the model-changed > signal only once a second (for example). Just did a test; I'm currently at 550 events per second being sent from one thread to another through the signal/slot mechanism. The sending and receiving threads are different, with the added complexities and slowdowns that brings for moving events into and out of shared queue buffers. I've also verified that it is not the model updates and/or repaints themselves that cause the slowdown, by having the signal receiver simply return without actually doing anything. Unless I find additional data that suggest that the signal/slot sending across threads is not the cause of the slowdowns of the main GUI updates, I will try to attempt an alternative method of communicating events between the threads. Like having a GUI main thread idle method that only acts on "worked thread" events when the main GUI thread is idle. Thanks, Marius K. -- [ signature omitted ]
Marius Kjeldahl wrote: > I've also verified that it is not the model updates and/or repaints > themselves that cause the slowdown, by having the signal receiver > simply return without actually doing anything. If your worker threads have their own event loops and timers, did you remember to use moveToThread()? If not, your timers may actually be running in the main thread's event loop. I've stumbled over this gotcha several times. --Dave -- [ signature omitted ]
Dave Smith wrote: > If your worker threads have their own event loops and timers, did you > remember to use moveToThread()? If not, your timers may actually be > running in the main thread's event loop. I've stumbled over this gotcha > several times. Yes, I've made sure they are running in their own threads and not in the main/GUI thread, and that the worked threads do not call any GUI stuff at all. I've also verified this by "sleeping" the main thread and verifying that ticks are still being sent from the worked thread. Thanks, Marius K. -- [ signature omitted ]
Marius Kjeldahl wrote: > I'm using Qt's signal/slots mechanism for communicating events from a > worker thread to the main application. The main application receives > these events and updates a related model (which again updates a view). > With lots of events from the main application, the GUI of the > application appears slow/sluggish (menu selection, popup menus, > repaints and similar), probably because the events from the GUI itself > is queued in the same queue as the events from the worker thread. > > Does anybody have any suggestion on what would be a good strategy for > making the GUI of the application appear faster (i.e. not > slow/sluggish)? Any way to prioritize "normal" GUI events, or turn the > priority for signals from the worked thread down? > > Thanks, > > Marius K. > > -- > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with > "unsubscribe" in the subject or the body. > List archive and information: http://lists.trolltech.com/qt-interest/ > > It may seem a simplistic and brush off answer, but have you run a profiler over your code? Sometimes it highlights surprising results. Under linux, try valgrind -tool=callgrind and kcachegrind to view, windows/osx I'm not familiar with the tools, so can't offer any suggestions there. -- [ signature omitted ]
Bill KING wrote: > It may seem a simplistic and brush off answer, but have you run a > profiler over your code? Sometimes it highlights surprising results. > Under linux, try valgrind -tool=callgrind and kcachegrind to view, > windows/osx I'm not familiar with the tools, so can't offer any > suggestions there. Hey, I appreciate all suggestions! Yes, I have run profiling using gprof/kprof, together with the in-code profiling that I am doing. Now I've also run it inside vagrlind/kcachegrind as you suggested and I've attached a screenshot. The "deep-down" processing of events seems to dominate the top of the list, which I guess confirms my suspicions: My current theory is that signal/slots isn't suitable for high-bandwidth worker threads. One other poster here suggested a more direct approach using postEvent which I haven't tried yet (but will). Another method would be to implement my own cross-thread mechanism which doesn't have to deal with the qt metatype system (which I suspect is to blame). The behaviour of the application itself leads me to believe that the actual GUI events gets posted at the "far back" of the queue of signals containing the worked thread events, and therefore it takes some time for the event loop to get to them, which makes it appear sluggish. I've run the application over night as well and it still runs with similar performance as shortly after starting it, so I doubt there's any resource leakage or similar that makes it slower. It also indicates that the application is able to process all the events _eventually_, or I guess there would be resource starvation. If you can read anything else from the provided screenshot feel free to share it with me. Thanks, Marius K.
Marius Kjeldahl wrote: > attached a screenshot. The "deep-down" processing of events seems to > dominate the top of the list, which I guess confirms my suspicions: No, 56% is spent in calculating the geometry of items. I.e.: for each update that you signal (no matter if you use signals or any other means of communication) you cause a change and cause a re-layout of your item-view (or whatever you are using). The (main) bottleneck here is not signal/slots (although that has some cost, too), but rather that the gui can't do millions of updates. Some post has suggested to reduce the number of updates. You can achieve that by things like * not invalidating the whole model every time (I am not saying you do), but using dataChanged for only relevant indices * using setUpdatesEnabled - i.e. block updates during heavy change ops and reenable later for a block update * dont trigger an update on each change but periodically poll your model for changes HTH Christoph -- [ signature omitted ]
Christoph Duelli wrote: > Marius Kjeldahl wrote: > >> attached a screenshot. The "deep-down" processing of events seems to >> dominate the top of the list, which I guess confirms my suspicions: > No, 56% is spent in calculating the geometry of items. > I.e.: for each update that you signal (no matter if you use signals or any > other means of communication) you cause a change and cause a re-layout of > your item-view (or whatever you are using). and repeated calls to itemHeight might be prevented by using uniformRowHeights in the view (if they *are* uniform, of course) -- [ signature omitted ]
Christoph Duelli wrote: > Christoph Duelli wrote: > > >> Marius Kjeldahl wrote: >> >> >>> attached a screenshot. The "deep-down" processing of events seems to >>> dominate the top of the list, which I guess confirms my suspicions: >>> >> No, 56% is spent in calculating the geometry of items. >> I.e.: for each update that you signal (no matter if you use signals or any >> other means of communication) you cause a change and cause a re-layout of >> your item-view (or whatever you are using). >> > > and repeated calls to itemHeight might be prevented by using > uniformRowHeights in the view (if they *are* uniform, of course) > > -- > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body. > List archive and information: http://lists.trolltech.com/qt-interest/ > > > I second this modification/information. To Marius:Without the callgrind output file to inspect in depth, it definately looks like it's spending a lot of time recalculating the itemheights (of interest are the QStyle calls). If you can reduce the number of updates, and definately set uniformRowHeights if they're definately uniform, then you may see some significant improvements. A tiny little note: The event queue is heavily locked, there's work in progress for 4.5 to try and speed up cross thread event processing, and yes it is a bit of a bottleneck, but I think in this case, reducing the size related calls will give you a good boost (QTreeViewPrivate::itemHeight, QCommonStylePrivate::viewItemSize for example will reduce both number of calls and time spent in that function and it's children). -- [ signature omitted ]
(previously the "Signals and GUI speed" thread) Further testing indicates it may no necessarily be related to signals/slots at all. I've now tried disabling all updates to the model after the intial model setup (some 10-15 rows with some 3-5 children each), and it still feels sluggish. I've now traced it down to this; even without any updates or visible changes to the view, the view generates continuous paint events when I move the mouse over the view. I've tracked it down by overriding the paintEvent method, pushing dots to stderr before calling the QTreeView::paintEvent handler directly in the overridden method. Any idea what is causing the continuous repaint behaviour from just moving the mouse around? I realize it would probably be possible to add some hovering decoration or similar, and that this may be the reason why paint methods are called when moving the mouse around, but triggering these when no visible updates are happening doesn't seem right (and causes massive sluggishness in the GUI). Thanks, Marius K. -- [ signature omitted ]
Marius Kjeldahl wrote: > (previously the "Signals and GUI speed" thread) Well, no wonder things were running slowly... After barking up the wrong trees for a while, and after staring on profiling data for a while, I got really suspicious about all the "sync" calls showing up in the profiling tree when I finally figured out that moving the mouse around on top of the widget was essential for getting useful profiling data. Turns out there was a leftover in my code that forced X11 to sync all updates continously with the X server. This is what was causing the sluggish behaviour I experienced. The code was left over after I was tracking down another bug demonstrating some trouble with qt's qpixmap caching. Here's the "culprit", which I believe is similar to running with "-sync": extern int _Xdebug; _Xdebug = 1; After removing this, the application seems quite snappy again, despite the high bandwidth signal/slot calls that I've talked about earlier. Until the current speed becomes a problem again, there are other things to test. Thanks, Marius K. -- [ signature omitted ]
Marius Kjeldahl wrote: > Marius Kjeldahl wrote: >> (previously the "Signals and GUI speed" thread) > > Well, no wonder things were running slowly... After barking up the > wrong trees for a while, and after staring on profiling data for a > while, I got really suspicious about all the "sync" calls showing up > in the profiling tree when I finally figured out that moving the mouse > around on top of the widget was essential for getting useful profiling > data. > > Turns out there was a leftover in my code that forced X11 to sync all > updates continously with the X server. This is what was causing the > sluggish behaviour I experienced. The code was left over after I was > tracking down another bug demonstrating some trouble with qt's qpixmap > caching. Here's the "culprit", which I believe is similar to running > with "-sync": > > extern int _Xdebug; > _Xdebug = 1; > > After removing this, the application seems quite snappy again, despite > the high bandwidth signal/slot calls that I've talked about earlier. > Until the current speed becomes a problem again, there are other > things to test. > > Thanks, > > Marius K. > > -- > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with > "unsubscribe" in the subject or the body. > List archive and information: http://lists.trolltech.com/qt-interest/ > > Good news ;) And I know I learned something today :) -- [ signature omitted ]
Am Mittwoch, 16. April 2008 schrieb Marius Kjeldahl: > My current theory is that signal/slots isn't suitable for high-bandwidth > worker threads. One other poster here suggested a more direct approach > using postEvent which I haven't tried yet (but will). Another method > would be to implement my own cross-thread mechanism which doesn't have > to deal with the qt metatype system (which I suspect is to blame). Signal/Slot could be the one to blame. I use events directly. And I only push the pointer to the data around. (Last one in the chain deletes it...) But never underestimate the gui. It could be that because the gui is a little slow on update/repaint the main event-loop isn't handled fast enough to push the events to the sub-threads event-loops... Arnold -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.