Results 1 to 8 of 8

Thread: QDoubleSpinBox setValue() performance issue

  1. #1
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    363
    Thanks
    87
    Thanked 12 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QDoubleSpinBox setValue() performance issue

    Hi there,

    on my gui I show a 3D model of a skeleton and around the skeleton I have approx. 20 QDoubleSpinBoxes that show the angles of the joints of the skeleton. I animate the 3D model by setting new joint angles every 12 ms. It works great. I can see a smooth animation and my CPU still can breathe.

    Now when I try to use the QDoubleSpinBoxes to display the actual numbers of the joint angles, my CPU almost dies and nothing moves. Here is what I do:

    Qt Code:
    1. void transferAnglesToSpinboxes()
    2. {
    3. disconnect(this, SIGNAL(inputValueChanged()), this, SLOT(jointAnglesChangedBySpinbox()));
    4.  
    5. headY->setValue(jointAngles["headY"]);
    6. headZ->setValue(jointAngles["headZ"]);
    7. rShouX->setValue(jointAngles["rShouX"]);
    8. rShouY->setValue(jointAngles["rShouY"]);
    9. rShouZ->setValue(jointAngles["rShouZ"]);
    10. rElbow->setValue(jointAngles["rElbow"]);
    11. rHipX->setValue(jointAngles["rHipX"]);
    12. rHipY->setValue(jointAngles["rHipY"]);
    13. rHipZ->setValue(jointAngles["rHipZ"]);
    14. rKnee->setValue(jointAngles["rKnee"]);
    15. rAnkX->setValue(jointAngles["rAnkX"]);
    16. rAnkY->setValue(jointAngles["rAnkY"]);
    17. lShouX->setValue(jointAngles["lShouX"]);
    18. lShouY->setValue(jointAngles["lShouY"]);
    19. lShouZ->setValue(jointAngles["lShouZ"]);
    20. lElbow->setValue(jointAngles["lElbow"]);
    21. lHipX->setValue(jointAngles["lHipX"]);
    22. lHipY->setValue(jointAngles["lHipY"]);
    23. lHipZ->setValue(jointAngles["lHipZ"]);
    24. lKnee->setValue(jointAngles["lKnee"]);
    25. lAnkX->setValue(jointAngles["lAnkX"]);
    26. lAnkY->setValue(jointAngles["lAnkY"]);
    27.  
    28. connect(this, SIGNAL(inputValueChanged()), this, SLOT(jointAnglesChangedBySpinbox()));
    29. }
    To copy to clipboard, switch view to plain text mode 

    Those are lots of setValue() calls to different spin boxes. The valueChanged() signals of all those QDoubleSpinBoxes are connected to a single inputValueChanged() signal, that I disconnect prior to copying the jointAngles hash into the QDoubleSpinBoxes and then I reconnect the signal again. I do this to suppress the valueChanged() signals that I only want to deal with, when the spin boxes were changed manually and not programatically.

    I isolated the update of the 3D model and the update of the spin boxes and I'm absolutely positive, that it's the setValue() calls that strain the CPU. The 3D model alone works fine, the spin boxes alone fry my machine.

    I don't understand. The calculation of a new pose of the skeleton for a given set of joint angles is actually quite heavy math, but obviously well manageable in 12 ms. But 20 setValue() calls are too much? Why why why?

  2. #2
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: QDoubleSpinBox setValue() performance issue

    Hi,

    that's really strange. For debug and more information please measure the time for the setValue()'s of all calls at one block. Is jointAngles a QHash? And by the way, why you are using signal and slots to communicate inside a class?


    Lykurg

  3. #3
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    363
    Thanks
    87
    Thanked 12 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QDoubleSpinBox setValue() performance issue

    I'm measuring it on Windows, so it's probably not much use. Tomorrow I can have a go at it on a Linux machine. Anyways, the result is still strange. Here is how I did the performance measuring:

    Qt Code:
    1. void transferAnglesToSpinboxes()
    2. {
    3. disconnect(this, SIGNAL(inputValueChanged()), this, SLOT(jointAnglesChangedBySpinbox()));
    4.  
    5. QTime time;
    6. time.start();
    7.  
    8. headY->setValue(jointAngles["headY"]);
    9. headZ->setValue(jointAngles["headZ"]);
    10. [...]
    11. lAnkX->setValue(jointAngles["lAnkX"]);
    12. lAnkY->setValue(jointAngles["lAnkY"]);
    13.  
    14. qDebug() << time.elapsed();
    15.  
    16. connect(this, SIGNAL(inputValueChanged()), this, SLOT(jointAnglesChangedBySpinbox()));
    17. }
    To copy to clipboard, switch view to plain text mode 

    The result is something like:
    0,16,15,16,16,42,15,16,0,16,16,15...say 16 ms.

    In the meantime I implemented a quick hack to protect the spin boxes from being updated too often like this:

    Qt Code:
    1. // An ugly quick hack to circumvent performance issues.
    2. if (lastTime.msecsTo(QTime::currentTime()) > 100)
    3. {
    4. lastTime = QTime::currentTime();
    5. transferAnglesToSpinboxes();
    6. }
    To copy to clipboard, switch view to plain text mode 

    With this protection is on, the performance measure shows:
    0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0...as if it were nothing.

    Is jointAngles a QHash?
    Yes.

    Why you are using signal and slots to communicate inside a class?
    I tried to explain in my first post, I guess it was too lame. Of course the spin boxes can be changed manually by the user and each of them emits an individual valueChanged() signal. This also happens when I set the value of the spin box programatically. But in the latter case I want to supress the valueChanged() signals. So what I did is I connected the valueChanged() signals of all the spin boxes to one inputValueChanged() signal of my class, which is then connected to a slot that handles the transfer of the spin box values into the jointAngles QHash. As you can see in my transferAnglesToSpinboxes() methid, this way I only need to disconnect one signal, when I change the spin boxes programatically. Otherwise I would have to disconnect and then reconnect 20 individual spin boxes.

  4. #4
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    363
    Thanks
    87
    Thanked 12 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QDoubleSpinBox setValue() performance issue

    But now that you made me think twice about it, I could solve it with a flag instead of signals and slots.

  5. #5
    Join Date
    Feb 2009
    Location
    Noida, India
    Posts
    517
    Thanks
    21
    Thanked 66 Times in 62 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QDoubleSpinBox setValue() performance issue

    there is also a function blockSignals(bool) for QObject class..maybe it can be useful to u..u can use it instead of flags

  6. #6
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    363
    Thanks
    87
    Thanked 12 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QDoubleSpinBox setValue() performance issue

    Quote Originally Posted by talk2amulya View Post
    there is also a function blockSignals(bool) for QObject class..maybe it can be useful to u..u can use it instead of flags
    Doesn't help because then I would have to block and unblock the signals of 20 spin boxes one by one.

  7. #7
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    363
    Thanks
    87
    Thanked 12 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QDoubleSpinBox setValue() performance issue

    For completeness I ran the performance measure on Linux.

    With the QTime guard I get:

    4, 6, 4, 5, 6, 4, 4, 5, 4, 1, 5, 5, 5, 5, 6, 4, 4, 4, 5, 6, 4, 5, 4, 6, 4, 5, 5, 6, 9, 4, 5 ...ms for the update of 20 QDoubleSpinBoxes

    and without the QTime guard:

    3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 3, 5, 4, 4, 3, 3, 4, 3, 3 ... even a bit faster.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QDoubleSpinBox setValue() performance issue

    Correct me if I'm wrong but if you change values to those spinboxes every 20ms, they need to be redrawn 50 times per second. 50 * 20 = 1000. That's how many times per second the paintEvent of the spinbox class is called.

    I suggest you do something like this:
    Qt Code:
    1. QVector<qreal> values(20, 0.0);
    2. QTimer *updateTimer = new QTimer(this);
    3. connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateBoxes()));
    4. updateTimer->start(500); // 2Hz
    5. //...
    6. void XX::updateBoxes(){
    7. for(int i=0;i<20;i++){
    8. qreal val = values[i];
    9. QDoubleSpinBox *sb = boxes[i];
    10. sb->setValue(val);
    11. }
    12. }
    To copy to clipboard, switch view to plain text mode 

    That's more or less what you did in your first approach. Just make sure the "transferAxesToSpinboxes()" method is called 1-2 times a second at most. You won't notice more values of 20 boxes per second anyway.

  9. The following user says thank you to wysota for this useful post:

    Cruz (17th February 2009)

Similar Threads

  1. Performance Issue
    By linuxdev in forum Qt Programming
    Replies: 1
    Last Post: 10th December 2008, 16:00

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.