Details
-
Bug
-
Resolution: Done
-
P2: Important
-
4.6.0
-
None
-
MacOS/X 10.6.2, 8-core 2.8GHz Intel Mac Pro, 20GB RAM
Description
When running Qt under MacOS/X, the amount of time it takes to create each widget in a widget tree increases substantially with the number of widgets already in the tree, if setAcceptDrops(true) has been called on any ancestor of the newly created widget. The user-visible effect of this is that windows with many drop-able widgets in them take a long time and a lot of CPU to open under MacOS/X. (This problem does not occur under Qt/Linux; I haven't tested under Qt/Windows)
1) On a Mac, compile the example program contained in the attached file (set_accept_drop_efficiency_problem.zip)
2) Run the resulting executable from the command line, like this:
./ge.app/Contents/MacOS/ge run_suite
3) The program will construct a series of widgets containing simple NxN grids of sub-widgets, and measure how long it takes to create and show each one. In the first series of tests, it will call setAcceptDrops(true) on the parent widget before populating the grid with sub-widgets; in the second series, it will not call setAcceptDrops(true). On my Mac, the results look like this (pay particular attention the avg time at the end of each line):
jeremy-friesners-mac-pro:grid_efficiency jaf$ ./main.app/Contents/MacOS/main run_suite
(WITH setAcceptDrops(true)): Time to construct a 10x10 widget grid: 57ms (avg 0.57ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 20x20 widget grid: 340ms (avg 0.85ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 30x30 widget grid: 1358ms (avg 1.51ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 40x40 widget grid: 3996ms (avg 2.50ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 50x50 widget grid: 9443ms (avg 3.78ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 60x60 widget grid: 19220ms (avg 5.34ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 70x70 widget grid: 35508ms (avg 7.25ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 80x80 widget grid: 61741ms (avg 9.65ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 90x90 widget grid: 100338ms (avg 12.39ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 100x100 widget grid: 154373ms (avg 15.44ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 10x10 widget grid: 26ms (avg 0.26ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 20x20 widget grid: 92ms (avg 0.23ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 30x30 widget grid: 201ms (avg 0.22ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 40x40 widget grid: 359ms (avg 0.22ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 50x50 widget grid: 565ms (avg 0.23ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 60x60 widget grid: 822ms (avg 0.23ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 70x70 widget grid: 1131ms (avg 0.23ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 80x80 widget grid: 1527ms (avg 0.24ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 90x90 widget grid: 1962ms (avg 0.24ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 100x100 widget grid: 2480ms (avg 0.25ms/widget)
4) Note that when setAcceptDrops(true) was called, the average time to create each sub-widget increases with the total number of widgets in the grid... from 0.57ms/widget in the 10x10 case up to 15.34ms/widget in the 100x100 case. In the series of trials where setAcceptDrops(true) is NOT called, on the other hand, the per-widget creation time remains roughly constant at around 0.24ms/widget.
The effect of this problem on my real-life application is that my larger windows (with around 2500 widgets in them) take about 15 seconds to open under MacOS/X, which isn't an acceptable level of performance. If I comment out the setAcceptDrops(true) calls, the time to open a large window drops to around 5 seconds, which is a good deal less bad... but of course then I can't drag anything into the window, which isn't acceptable either.
For comparison, here is the same program running inside a VMWare Fusion Linux VM on the same Mac. Note that not only are the widget creation times much better (0.04ms/widget vs 0.24ms/widget) but the per-widget creation time remains constant in all cases. Given Qt 4's "alien widget" support, I think it is reasonable to expect similar performance under MacOS/X as well.
jaf@jeremy-desktop:~/software/grid_efficiency$ ./ge run_suite
(WITH setAcceptDrops(true)): Time to construct a 10x10 widget grid: 16ms (avg 0.16ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 20x20 widget grid: 11ms (avg 0.03ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 30x30 widget grid: 40ms (avg 0.04ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 40x40 widget grid: 44ms (avg 0.03ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 50x50 widget grid: 63ms (avg 0.03ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 60x60 widget grid: 92ms (avg 0.03ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 70x70 widget grid: 128ms (avg 0.03ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 80x80 widget grid: 167ms (avg 0.03ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 90x90 widget grid: 217ms (avg 0.03ms/widget)
(WITH setAcceptDrops(true)): Time to construct a 100x100 widget grid: 266ms (avg 0.03ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 10x10 widget grid: 4ms (avg 0.04ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 20x20 widget grid: 37ms (avg 0.09ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 30x30 widget grid: 33ms (avg 0.04ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 40x40 widget grid: 45ms (avg 0.03ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 50x50 widget grid: 63ms (avg 0.03ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 60x60 widget grid: 84ms (avg 0.02ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 70x70 widget grid: 120ms (avg 0.02ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 80x80 widget grid: 161ms (avg 0.03ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 90x90 widget grid: 207ms (avg 0.03ms/widget)
(WITHOUT setAcceptDrops(true)): Time to construct a 100x100 widget grid: 259ms (avg 0.03ms/widget)