Page 1 of 4 123 ... LastLast
Results 1 to 20 of 80

Thread: GraphicsView performance problems

  1. #1
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default GraphicsView performance problems

    Hi,
    Actually this is continuation of this thread but the question is quite different.
    I am running into performance problems when multiple items are moved. The peformance is better when I disable the children of resistor(nodes and text item). But I want those features in my app. Also the grid look corrupted when items are moved. Any suggestion for that ?
    Here is the profile output
    Flat profile:

    Each sample counts as 0.01 seconds.
    % cumulative self self total
    time seconds seconds calls Ts/call Ts/call name
    75.08 0.03 0.03 GridScene::drawBackground(QPainter*, QRectF const&)
    25.03 0.04 0.01 Resistor::boundingRect() const
    0.00 0.04 0.00 119168 0.00 0.00 QVarLengthArray<QLineF, 100>::realloc(int, int)
    Here is the shorter version of the code. Select all items and move so that you can see what I mean. Please help me.

    Qt Code:
    1. #include <QtGui>
    2.  
    3. class GridScene : public QGraphicsScene
    4. {
    5. public:
    6. GridScene(qreal x, qreal y, qreal w, qreal h)
    7. : QGraphicsScene(x, y, w, h)
    8. { }
    9.  
    10. protected:
    11. void drawBackground(QPainter *painter, const QRectF &rect)
    12. {
    13. const int gridSize = 25;
    14. painter->setPen(QPen(Qt::darkGreen,0));
    15. qreal left = int(rect.left()) - (int(rect.left()) % gridSize);
    16. qreal top = int(rect.top()) - (int(rect.top()) % gridSize);
    17.  
    18. QVarLengthArray<QLineF, 100> lines;
    19.  
    20. for (qreal x = left; x < rect.right(); x += gridSize)
    21. lines.append(QLineF(x, rect.top(), x, rect.bottom()));
    22. for (qreal y = top; y < rect.bottom(); y += gridSize)
    23. lines.append(QLineF(rect.left(), y, rect.right(), y));
    24.  
    25. painter->drawLines(lines.data(), lines.size());
    26. }
    27. };
    28.  
    29. class Node : public QGraphicsItem
    30. {
    31. public:
    32. Node(QPointF pos ,QGraphicsItem *par = 0, QGraphicsScene *sc = 0) : QGraphicsItem(par,sc)
    33. {
    34. setPos(pos);
    35. setFlags(0);
    36. setAcceptedMouseButtons(0);
    37. }
    38.  
    39. void paint(QPainter* p,const QStyleOptionGraphicsItem *, QWidget *)
    40. {
    41. p->setPen(Qt::darkRed);
    42. p->drawEllipse(QRectF(-3, -3, 2*3, 2*3));
    43. }
    44.  
    45. QPainterPath shape() const
    46. {
    47. path.addEllipse(QRectF(-3, -3, 2*3, 2*3));
    48. return path;
    49. }
    50.  
    51. QRectF boundingRect() const
    52. {
    53. return QRectF(-3, -3, 2*3, 2*3);
    54. }
    55.  
    56. };
    57.  
    58. class Resistor : public QGraphicsItem
    59. {
    60. public:
    61. Resistor(QGraphicsItem *par = 0, QGraphicsScene *scene = 0) : QGraphicsItem(par,scene)
    62. {
    63. setFlags(ItemIsMovable | ItemIsSelectable | ItemIsFocusable);
    64. // comment the following 4 lines to see the performance difference
    65. QGraphicsTextItem *t = new QGraphicsTextItem("R1 = 100k",this,scene);
    66. t->setPos(0,-35);
    67. new Node(QPointF(-30,0),this,scene);
    68. new Node(QPointF(30,0),this,scene);
    69. }
    70.  
    71. void paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *)
    72. {
    73. if(!(o->state & QStyle::State_Open))
    74. p->setPen(Qt::darkBlue);
    75. if(o->state & QStyle::State_Selected)
    76. p->setPen(QPen(Qt::darkGray,1));
    77.  
    78. p->drawLine(-18, -9, 18, -9);
    79. p->drawLine( 18, -9, 18, 9);
    80. p->drawLine( 18, 9,-18, 9);
    81. p->drawLine(-18, 9,-18, -9);
    82. p->drawLine(-27, 0,-18, 0);
    83. p->drawLine( 18, 0, 27, 0);
    84. }
    85.  
    86. QRectF boundingRect() const
    87. {
    88. qreal pw = 0.5;
    89. return QRectF(-27,-9,54,18).adjusted(-pw,-pw,pw,pw);
    90. }
    91. };
    92.  
    93. int main(int argc,char *argv[])
    94. {
    95. QApplication app(argc,argv);
    96. GridScene scene(0,0,1024,768);
    97. for(int j = 2; j < 4; ++j)
    98. for(int i = 1; i <11; ++i)
    99. {
    100. Resistor *r = new Resistor(0,&scene);
    101. r->setPos(j*100, i * 50);
    102. }
    103. QGraphicsView *view = new QGraphicsView(&scene);
    104. view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    105. view->setDragMode(QGraphicsView::RubberBandDrag);
    106. view->show();
    107. return app.exec();
    108. }
    To copy to clipboard, switch view to plain text mode 
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  2. #2
    Join Date
    May 2006
    Location
    Bangalore,India
    Posts
    235
    Thanks
    7
    Thanked 25 Times in 24 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: GraphicsView performance problems

    In your main function just add

    view->setViewport(new QGLWidget);

    I am sure, this will improve the performence.
    please add QGLWidget include file & path in settings.

  3. #3
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by rajesh View Post
    In your main function just add

    view->setViewport(new QGLWidget);

    I am sure, this will improve the performence.
    please add QGLWidget include file & path in settings.
    Wish I could have done that but I can't use opengl since the app is targeted to platforms even without opengl support.
    But I tested it now and found some improvement but sadly I can't use it.
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

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

    Default Re: GraphicsView performance problems

    What if you disable the render hints while painting the background? Do you get a significant performance gain? Could you also please include information about profiling for drawBackground()? It might require a recompilation of Qt!

  5. #5
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by wysota View Post
    What if you disable the render hints while painting the background? Do you get a significant performance gain?
    Disabling render hints didn't improve the performance significantly.

    Quote Originally Posted by wysota View Post
    Could you also please include information about profiling for drawBackground()?!It might require a recompilation of Qt
    I can do that but i may have to do re-recompilation later
    Before that, do you see any problems in my code ? Did you see performance difference after commenting the lines ? Atleast I would like to wait till Bitto answers something since compiling qt is time consuming!
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  6. #6
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    As I already pointed out that performance is better without those nodes and textitems as children. Does that mean drawBackground() is being called twice for same area ? Does the framework lack any optimization in calculating this before hand ?
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  7. #7
    Join Date
    May 2006
    Location
    Bangalore,India
    Posts
    235
    Thanks
    7
    Thanked 25 Times in 24 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: GraphicsView performance problems

    drawBackground() get called every time whenever your window painted, means when ever you move window or resize..

  8. #8
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by rajesh View Post
    drawBackground() get called every time whenever your window painted, means when ever you move window or resize..
    No. That is just one of the case. drawBackground() is called always before updating the required item(eg when its moved) with the probably the item's bounding rect. You can check that by just printing something say qDebug() << rect; in the method.
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  9. #9
    Join Date
    Jan 2006
    Posts
    128
    Thanked 28 Times in 27 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: GraphicsView performance problems

    Quote Originally Posted by Gopala Krishna View Post
    Also the grid look corrupted when items are moved. Any suggestion for that ?
    In my experience floating point arithmetic is always a nice way to get unexpected results...

    Have you tried using QLine instead of QLineF
    (It might give you a little speedup too, since often integer calculations are faster than floating point calculations.)


    Also, do you know which rounding functions the int cast uses?
    Does it "round to nearest"? Does it do a "floor"? Does it do a "ceil"?
    It might make a difference, so you might want to be explicit there.


    Good luck :-)
    Last edited by camel; 17th February 2007 at 10:46. Reason: finish a half done rewrite of the first sentence...looks better now :-)

  10. #10
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by camel View Post
    In my experience loating point arithmetic is always a nice way to get unexpected results (in my experience)...

    Have you tried using QLine instead of QLineF
    (It might give you a little speedup too, since often integer calculations are faster than floating point calculations.)


    Also, do you know which rounding functions the int cast uses?
    Does it "round to nearest"? Does it do a "floor"? Does it do a "ceil"?
    It might make a difference, so you might want to be explicit there.


    Good luck :-)
    I think you are right. I will test with QLine since I don't need floating points for the grid. Thanks for pointing this.
    Last edited by Gopala Krishna; 17th February 2007 at 10:47. Reason: updated contents
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  11. #11
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    I tested with QLine but that didn't make a difference. Also i am not sure what the int cast does - i feel it just takes int part without rounding. But do you think this will make a difference since I am following one convention in all places in drawBackground() ?
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  12. #12
    Join Date
    Jan 2006
    Posts
    128
    Thanked 28 Times in 27 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: GraphicsView performance problems

    Quote Originally Posted by Gopala Krishna View Post
    I tested with QLine but that didn't make a difference. Also i am not sure what the int cast does - i feel it just takes int part without rounding. But do you think this will make a difference since I am following one convention in all places in drawBackground() ?
    It does make a difference:
    Qt Code:
    1. void drawBackground(QPainter *painter, const QRectF &rect)
    2. {
    3. const int gridSize = 25;
    4.  
    5. const int realLeft = static_cast<int>(std::floor(rect.left()));
    6. const int realRight = static_cast<int>(std::ceil(rect.right()));
    7. const int realTop = static_cast<int>(std::floor(rect.top()));
    8. const int realBottom = static_cast<int>(std::ceil(rect.bottom()));
    9.  
    10.  
    11. const int firstLeftGridLine = realLeft - (realLeft % gridSize);
    12. const int firstTopGridLine = realTop - (realTop % gridSize);
    13.  
    14. QVarLengthArray<QLine, 100> lines;
    15.  
    16. for (int x = firstLeftGridLine; x <= realRight; x += gridSize)
    17. lines.append(QLine(x, realTop, x, realBottom));
    18. for (int y = firstTopGridLine; y <= realBottom; y += gridSize)
    19. lines.append(QLine(realLeft, y, realRight, y));
    20.  
    21.  
    22. painter->setPen(QPen(Qt::darkGreen,0));
    23. painter->drawLines(lines.data(), lines.size());
    24. }
    To copy to clipboard, switch view to plain text mode 

    As you see I make three changes
    a) integer instead of float
    b) using the containing integer rect as basis (i.e. the smallest integer rect that contains the float rect)
    c) I changed the "<" in your for loops to a "<=", i thing part of your corruption was that it did not always repaint the grid when the line was at the border of the exposed rect.


    The result: no more corruption of the grid...only weird color changes that I am trying to track down ;-)


    EDIT: Of course you now need:
    Qt Code:
    1. #include <cmath>
    To copy to clipboard, switch view to plain text mode 
    for the floor, and ceil to work ;-)
    Last edited by camel; 17th February 2007 at 11:34.

  13. The following user says thank you to camel for this useful post:

    Gopala Krishna (17th February 2007)

  14. #13
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by camel View Post
    ...
    The result: no more corruption of the grid...only weird color changes that I am trying to track down ;-)
    for the floor, and ceil to work ;-)
    As you said no more corruption but yeah even I am cracking my head a lot on how to remove those weird color changes.
    But I tell you I found one magic while experimenting. Try , its fun.

    change the bounding rect of Resistor to
    Qt Code:
    1. QRectF Resistor::boundingRect() const
    2. {
    3. qreal pw = 0.5;
    4. return QRectF(-47,-9,47*2,18).adjusted(-pw,-pw,pw,pw);
    5. }
    To copy to clipboard, switch view to plain text mode 

    Check for performance now!!
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

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

    Default Re: GraphicsView performance problems

    I really suggest to recompile Qt with profiling information. You're shooting blind now. Profiling will give you the exact bottleneck point. Furthermore make sure your app is compiled correctly, I think you should be able to have a decomposition of the drawBackground() method in the profiling information as well. It should then tell you which part of the method takes most time and it should be possible to obtain without recompiling Qt.

  16. #15
    Join Date
    Jan 2006
    Posts
    128
    Thanked 28 Times in 27 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: GraphicsView performance problems

    Hey,

    I just changed your source a bit so that the boundingrects and shapes are only calculated once...

    check if that helps with the performance a bit...

    (since I cannot realy judge it here... :-)



    I also found that the grid-color-problem is lessend (but not gone) when you fill the rect in the draw background,

    And the error is gone completely when you turn off anti-aliasing.

    Might be a Qt-Bug :-/


    Anyways, my version of your code :-)
    Qt Code:
    1. #include <QtGui>
    2. #include <cmath>
    3.  
    4. class GridScene : public QGraphicsScene
    5. {
    6. public:
    7. GridScene(qreal x, qreal y, qreal w, qreal h)
    8. : QGraphicsScene(x, y, w, h)
    9. { }
    10.  
    11. protected:
    12. void drawBackground(QPainter *painter, const QRectF &rect)
    13. {
    14. const int gridSize = 25;
    15.  
    16. const int realLeft = static_cast<int>(std::floor(rect.left()));
    17. const int realRight = static_cast<int>(std::ceil(rect.right()));
    18. const int realTop = static_cast<int>(std::floor(rect.top()));
    19. const int realBottom = static_cast<int>(std::ceil(rect.bottom()));
    20.  
    21.  
    22. const int firstLeftGridLine = realLeft - (realLeft % gridSize);
    23. const int firstTopGridLine = realTop - (realTop % gridSize);
    24.  
    25. QVarLengthArray<QLine, 100> lines;
    26.  
    27. for (int x = firstLeftGridLine; x <= realRight; x += gridSize)
    28. lines.append(QLine(x, realTop, x, realBottom));
    29. for (int y = firstTopGridLine; y <= realBottom; y += gridSize)
    30. lines.append(QLine(realLeft, y, realRight, y));
    31.  
    32. //If you uncomment this, you will find the color problem lessened...
    33. //why? well your guess is as good as mine ;-)
    34. // painter->fillRect(QRect(QPoint(realLeft, realTop), QPoint(realRight, realBottom)), QBrush(Qt::white));
    35.  
    36. painter->setOpacity(1.0);
    37. painter->setPen(QPen(Qt::darkGreen,0));
    38. painter->drawLines(lines.data(), lines.size());
    39. }
    40. };
    41.  
    42. namespace {
    43. static inline QPainterPath constructNodeShape(const QRect& elipseRect)
    44. {
    45. path.addEllipse(elipseRect);
    46. return path;
    47. }
    48. }
    49.  
    50. class Node : public QGraphicsItem
    51. {
    52. public:
    53. Node(QPointF pos ,QGraphicsItem *par = 0, QGraphicsScene *sc = 0)
    54. : QGraphicsItem(par,sc),
    55. elipseRect(-3, -3, 2*3, 2*3),
    56. elipseShape(constructNodeShape(elipseRect))
    57. {
    58. setPos(pos);
    59. setFlags(0);
    60. setAcceptedMouseButtons(0);
    61. }
    62.  
    63. void paint(QPainter* p,const QStyleOptionGraphicsItem *, QWidget *)
    64. {
    65. p->setPen(Qt::darkRed);
    66. p->setBrush(Qt::NoBrush);
    67. p->setOpacity(1.0);
    68. p->drawEllipse(elipseRect);
    69. }
    70.  
    71. QPainterPath shape() const
    72. {
    73. return elipseShape;
    74. }
    75.  
    76. QRectF boundingRect() const
    77. {
    78. return elipseRect;
    79. }
    80.  
    81. protected:
    82. const QRect elipseRect;
    83. const QPainterPath elipseShape;
    84. };
    85.  
    86. class Resistor : public QGraphicsItem
    87. {
    88. public:
    89. Resistor(QGraphicsItem *par = 0, QGraphicsScene *scene = 0)
    90. : QGraphicsItem(par,scene),
    91. resistorBox(-18, -9, 36, 18),
    92. connectors(new QLine[2])
    93. {
    94. setFlags(ItemIsMovable | ItemIsSelectable | ItemIsFocusable);
    95. // comment the following 4 lines to see the performance difference
    96. QGraphicsTextItem *t = new QGraphicsTextItem("R1 = 100k",this,scene);
    97. t->setPos(0,-35);
    98. new Node(QPointF(-30,0),this,scene);
    99. new Node(QPointF(30,0),this,scene);
    100.  
    101. connectors[0] = QLine(-27, 0, -18, 0);
    102. connectors[1] = QLine(18, 0, 27, 0);
    103.  
    104. boundingBox |= resistorBox;
    105. boundingBox |= QRectF(connectors[0].x1(), connectors[0].y1(), connectors[0].x2(), connectors[0].y2() );
    106. boundingBox |= QRectF(connectors[1].x1(), connectors[1].y1(), connectors[1].x2(), connectors[1].y2() );
    107. boundingBox.adjust(-0.5, -0.5, 0.5, 0.5);
    108. }
    109.  
    110. ~Resistor()
    111. {
    112. delete[] connectors;
    113. }
    114.  
    115. void paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *)
    116. {
    117. if(!(o->state & QStyle::State_Open))
    118. p->setPen(Qt::darkBlue);
    119. if(o->state & QStyle::State_Selected)
    120. p->setPen(QPen(Qt::darkGray,1));
    121.  
    122. p->setBrush(Qt::NoBrush);
    123. p->drawRect(resistorBox);
    124. p->drawLines(connectors, 2);
    125. }
    126.  
    127. QRectF boundingRect() const
    128. {
    129. return boundingBox;
    130. }
    131.  
    132. private:
    133. QRect resistorBox;
    134. QLine* connectors;
    135. QRectF boundingBox;
    136. };
    137.  
    138. int main(int argc,char *argv[])
    139. {
    140. QApplication app(argc,argv);
    141. GridScene scene(0,0,1024,768);
    142. for(int j = 2; j < 4; ++j)
    143. for(int i = 1; i <11; ++i)
    144. {
    145. Resistor *r = new Resistor(0,&scene);
    146. r->setPos(j*100, i * 50);
    147. }
    148. QGraphicsView *view = new QGraphicsView(&scene);
    149. // Turn of antialiasing and the color problem is gone...
    150. view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    151. view->setDragMode(QGraphicsView::RubberBandDrag);
    152. view->show();
    153. return app.exec();
    154. }
    To copy to clipboard, switch view to plain text mode 

  17. #16
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by wysota View Post
    I really suggest to recompile Qt with profiling information. You're shooting blind now. Profiling will give you the exact bottleneck point. Furthermore make sure your app is compiled correctly, I think you should be able to have a decomposition of the drawBackground() method in the profiling information as well. It should then tell you which part of the method takes most time and it should be possible to obtain without recompiling Qt.
    ok finally I agree. You are right . I guess there is no decomposition because most method are inlined. Well I'll do that recompilation tomorrow(nice job in the weekend )
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

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

    Default Re: GraphicsView performance problems

    First do this (or something simmilar):
    Qt Code:
    1. void drawLines(QPainter *painter, QVarLengthArray<QLineF, 100> &lines){
    2. painter->drawLines(lines.data(), lines.size());
    3. }
    4.  
    5. void setupArray(QVarLengthArray<QLineF, 100> &lines){
    6. const int gridSize = 25;
    7. qreal left = int(rect.left()) - (int(rect.left()) % gridSize);
    8. qreal top = int(rect.top()) - (int(rect.top()) % gridSize);
    9. for (qreal x = left; x < rect.right(); x += gridSize)
    10. lines.append(QLineF(x, rect.top(), x, rect.bottom()));
    11. for (qreal y = top; y < rect.bottom(); y += gridSize)
    12. lines.append(QLineF(rect.left(), y, rect.right(), y));
    13. }
    14. void drawBackground(QPainter *painter, const QRectF &rect){
    15. painter->setPen(QPen(Qt::darkGreen,0));
    16. QVarLengthArray<QLineF, 100> lines;
    17. setupArray(lines);
    18. drawLines(painter, lines);
    19. }
    To copy to clipboard, switch view to plain text mode 

    This should allow you to measure how much time does it take to setup the array and how much to paint it.

  19. #18
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by camel View Post
    Hey,

    I just changed your source a bit so that the boundingrects and shapes are only calculated once...

    check if that helps with the performance a bit...

    (since I cannot realy judge it here... :-)



    I also found that the grid-color-problem is lessend (but not gone) when you fill the rect in the draw background,

    And the error is gone completely when you turn off anti-aliasing.

    Might be a Qt-Bug :-/


    Anyways, my version of your code :-)
    Qt Code:
    1. #include <QtGui>
    2. #include <cmath>
    3.  
    4. class GridScene : public QGraphicsScene
    5. {
    6. public:
    7. ....
    To copy to clipboard, switch view to plain text mode 
    I am really thankful to your support.

    Yeah you are right. The colouring is gone without antialiasing. But I also experimented with one more thing.
    I did this in drawBackground() which didn't alter much
    Qt Code:
    1. void GridScene::drawBackground(QPainter *p, const QRectF& rect) const
    2. {
    3. QPainter::RenderHints rh = p->renderHints();
    4. p->setRenderHints(0);
    5. ...
    6. p->setRenderHints(rh);
    7. }
    To copy to clipboard, switch view to plain text mode 
    Should be Qt bug I believe.

    Calculating bounding rect beforehand did show improvement in performance. But I feel the main performance blow is in drawBackground(). Somehow I feel that drawBackground() is called more than required times which is causing all these. For example try with this
    Qt Code:
    1. view->setCacheMode(QGraphicsView::CacheBackground);
    To copy to clipboard, switch view to plain text mode 
    The performance improves but the background corrupts when we scroll. Also as I pointed in my last but one post, increasing bounding rect of resistor so that it covers node also sigificantly improved performance. This suggests that the rects are not ORred properly before updating that region. ( I may be wrong, correct me if I am)
    Well to exactly solve this we need to profile the code (with profiling enabled for qt lib) or use some intelligent techniques (which I am not aware of )
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  20. #19
    Join Date
    Jan 2006
    Posts
    128
    Thanked 28 Times in 27 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: GraphicsView performance problems

    Well, I already did profile it globally and found something rather interesting.

    There is no use, trying to draw anything via the qpainter->draw(Rect, Elipsis, Polygons) whatever in Graphics view, since it is going to be converted to a painterpath anyways.


    That means, that for every paint, you create a new painterpath, which means that you need to allocate memory, which is slow.

    Why a painterpath?
    If you check the x11 paintengine, you see that as soon as antialiasing is enabled (or there is a certain amount of TxTranslate, whatever that means), drawing is done using the "path_fallback", which means primitives are first converted to paths before being drawn.
    Why? No clue ;-)

    But as a result that means, if you draw a lot of (rects, ellipses and polygons, lines...), use a painterpath instead. Preferably even one that you do not recalculate every time you are asked to draw something.. :-)


    The source after this transition:
    Qt Code:
    1. #include <QtGui>
    2. #include <cmath>
    3.  
    4. class GridScene : public QGraphicsScene
    5. {
    6. public:
    7. GridScene(qreal x, qreal y, qreal w, qreal h)
    8. : QGraphicsScene(x, y, w, h)
    9. { }
    10.  
    11. protected:
    12. void drawBackground(QPainter *painter, const QRectF &rect)
    13. {
    14. const int gridSize = 25;
    15.  
    16. const int realLeft = static_cast<int>(std::floor(rect.left()));
    17. const int realRight = static_cast<int>(std::ceil(rect.right()));
    18. const int realTop = static_cast<int>(std::floor(rect.top()));
    19. const int realBottom = static_cast<int>(std::ceil(rect.bottom()));
    20.  
    21.  
    22. const int firstLeftGridLine = realLeft - (realLeft % gridSize);
    23. const int firstTopGridLine = realTop - (realTop % gridSize);
    24.  
    25. QPainterPath background;
    26.  
    27. for (int x = firstLeftGridLine; x <= realRight; x += gridSize) {
    28. background.moveTo(x, realTop);
    29. background.lineTo(x, realBottom);
    30. background.closeSubpath();
    31. }
    32. for (int y = firstTopGridLine; y <= realBottom; y += gridSize) {
    33. background.moveTo(realLeft, y);
    34. background.lineTo(realRight, y);
    35. background.closeSubpath();
    36. }
    37.  
    38. //If you uncomment this, you will find the color problem lessened...
    39. //why? well your guess is as good as mine ;-)
    40. // painter->fillRect(QRect(QPoint(realLeft, realTop), QPoint(realRight, realBottom)), QBrush(Qt::white));
    41.  
    42. painter->setOpacity(1.0);
    43. painter->setPen(QPen(Qt::darkGreen,0));
    44. painter->drawPath(background);
    45. }
    46. };
    47.  
    48. namespace {
    49. static inline QPainterPath constructNodeShape(const QRect& elipseRect)
    50. {
    51. path.addEllipse(elipseRect);
    52. return path;
    53. }
    54. }
    55.  
    56. class Node : public QGraphicsItem
    57. {
    58. public:
    59. Node(QPointF pos ,QGraphicsItem *par = 0, QGraphicsScene *sc = 0)
    60. : QGraphicsItem(par,sc),
    61. elipseRect(-3, -3, 2*3, 2*3),
    62. elipseShape(constructNodeShape(elipseRect))
    63. {
    64. setPos(pos);
    65. setFlags(0);
    66. setAcceptedMouseButtons(0);
    67. }
    68.  
    69. void paint(QPainter* p,const QStyleOptionGraphicsItem *, QWidget *)
    70. {
    71. p->setPen(Qt::darkRed);
    72. p->setBrush(Qt::NoBrush);
    73. p->setOpacity(1.0);
    74.  
    75. p->drawPath(elipseShape);
    76. }
    77.  
    78. QPainterPath shape() const
    79. {
    80. return elipseShape;
    81. }
    82.  
    83. QRectF boundingRect() const
    84. {
    85. return elipseRect;
    86. }
    87.  
    88. protected:
    89. const QRect elipseRect;
    90. const QPainterPath elipseShape;
    91. };
    92.  
    93. class Resistor : public QGraphicsItem
    94. {
    95. public:
    96. Resistor(QGraphicsItem *par = 0, QGraphicsScene *scene = 0)
    97. : QGraphicsItem(par,scene)
    98. {
    99. setFlags(ItemIsMovable | ItemIsSelectable | ItemIsFocusable);
    100. // comment the following 4 lines to see the performance difference
    101. QGraphicsTextItem *t = new QGraphicsTextItem("R1 = 100k",this,scene);
    102. t->setPos(0,-35);
    103. new Node(QPointF(-30,0),this,scene);
    104. new Node(QPointF(30,0),this,scene);
    105.  
    106.  
    107. resistorPath.addRect(QRectF(-18.0, -9.0, 36.0, 18.0));
    108. resistorPath.moveTo(-27, 0);
    109. resistorPath.lineTo(-18, 0);
    110. resistorPath.closeSubpath();
    111. resistorPath.moveTo(18, 0);
    112. resistorPath.lineTo(27, 0);
    113. resistorPath.closeSubpath();
    114.  
    115. boundingBox = resistorPath.boundingRect();
    116. }
    117.  
    118. void paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *)
    119. {
    120. if(!(o->state & QStyle::State_Open))
    121. p->setPen(Qt::darkBlue);
    122. if(o->state & QStyle::State_Selected)
    123. p->setPen(QPen(Qt::darkGray,1));
    124.  
    125. p->setBrush(Qt::NoBrush);
    126. p->drawPath(resistorPath);
    127. }
    128.  
    129. QRectF boundingRect() const
    130. {
    131. return boundingBox;
    132. }
    133.  
    134. private:
    135. QPainterPath resistorPath;
    136. QRectF boundingBox;
    137. };
    138.  
    139. int main(int argc,char *argv[])
    140. {
    141. QApplication app(argc,argv);
    142. GridScene scene(0,0,1024,768);
    143. for(int j = 2; j < 4; ++j)
    144. for(int i = 1; i <11; ++i)
    145. {
    146. Resistor *r = new Resistor(0,&scene);
    147. r->setPos(j*100, i * 50);
    148. }
    149. QGraphicsView *view = new QGraphicsView(&scene);
    150. // Turn of antialiasing and the color problem is gone...
    151. view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    152. view->setDragMode(QGraphicsView::RubberBandDrag);
    153. view->show();
    154. return app.exec();
    155. }
    To copy to clipboard, switch view to plain text mode 

  21. #20
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GraphicsView performance problems

    Quote Originally Posted by wysota View Post
    First do this (or something simmilar):
    Qt Code:
    1. void drawLines(QPainter *painter, QVarLengthArray<QLineF, 100> &lines){
    2. painter->drawLines(lines.data(), lines.size());
    3. }
    4.  
    5. void setupArray(QVarLengthArray<QLineF, 100> &lines){
    6. const int gridSize = 25;
    7. qreal left = int(rect.left()) - (int(rect.left()) % gridSize);
    8. qreal top = int(rect.top()) - (int(rect.top()) % gridSize);
    9. for (qreal x = left; x < rect.right(); x += gridSize)
    10. lines.append(QLineF(x, rect.top(), x, rect.bottom()));
    11. for (qreal y = top; y < rect.bottom(); y += gridSize)
    12. lines.append(QLineF(rect.left(), y, rect.right(), y));
    13. }
    14. void drawBackground(QPainter *painter, const QRectF &rect){
    15. painter->setPen(QPen(Qt::darkGreen,0));
    16. QVarLengthArray<QLineF, 100> lines;
    17. setupArray(lines);
    18. drawLines(painter, lines);
    19. }
    To copy to clipboard, switch view to plain text mode 

    This should allow you to measure how much time does it take to setup the array and how much to paint it.
    Ok I did that, the profile now says
    Flat profile:

    Each sample counts as 0.01 seconds.
    % cumulative self self total
    time seconds seconds calls Ts/call Ts/call name
    50.05 0.02 0.02 Node:: paint(QPainter*, QStyleOptionGraphicsItem const*, QWidget*)
    25.03 0.03 0.01 GridScene::drawBackground(QPainter*, QRectF const&)
    25.03 0.04 0.01 Resistor::boundingRect() const
    0.00 0.04 0.00 192004 0.00 0.00 QVarLengthArray<QLineF, 100>::realloc(int, int)
    0.00 0.04 0.00 36506 0.00 0.00 GridScene::setupArray(QVarLengthArray<QLineF, 100>&, QRectF const&)
    0.00 0.04 0.00 36506 0.00 0.00 GridScene::drawLines(QPainter*, QVarLengthArray<QLineF, 100>&)
    0.00 0.04 0.00 1 0.00 0.00 global constructors keyed to _ZN9GridScene9drawLinesEP8QPainterR15QVarLengthArr ayI6QLineFLi100EE
    0.00 0.04 0.00 1 0.00 0.00 __static_initialization_and_destruction_0(int, int)
    Further

    Call graph (explanation follows)


    granularity: each sample hit covers 2 byte(s) for 24.97% of 0.04 seconds

    index % time self children called name
    <spontaneous>
    [1] 50.0 0.02 0.00 Node:: paint(QPainter*, QStyleOptionGraphicsItem const*, QWidget*) [1]
    -----------------------------------------------
    <spontaneous>
    [2] 25.0 0.01 0.00 GridScene::drawBackground(QPainter*, QRectF const&) [2]
    0.00 0.00 36506/36506 GridScene::setupArray(QVarLengthArray<QLineF, 100>&, QRectF const&) [12]
    0.00 0.00 36506/36506 GridScene::drawLines(QPainter*, QVarLengthArray<QLineF, 100>&) [13]
    -----------------------------------------------
    <spontaneous>
    [3] 25.0 0.01 0.00 Resistor::boundingRect() const [3]
    -----------------------------------------------
    0.00 0.00 192004/192004 GridScene::setupArray(QVarLengthArray<QLineF, 100>&, QRectF const&) [12]
    [11] 0.0 0.00 0.00 192004 QVarLengthArray<QLineF, 100>::realloc(int, int) [11]
    -----------------------------------------------
    0.00 0.00 36506/36506 GridScene::drawBackground(QPainter*, QRectF const&) [2]
    [12] 0.0 0.00 0.00 36506 GridScene::setupArray(QVarLengthArray<QLineF, 100>&, QRectF const&) [12]
    0.00 0.00 192004/192004 QVarLengthArray<QLineF, 100>::realloc(int, int) [11]
    -----------------------------------------------
    0.00 0.00 36506/36506 GridScene::drawBackground(QPainter*, QRectF const&) [2]
    [13] 0.0 0.00 0.00 36506 GridScene::drawLines(QPainter*, QVarLengthArray<QLineF, 100>&) [13]
    -----------------------------------------------
    0.00 0.00 1/1 __do_global_ctors_aux [25]
    [14] 0.0 0.00 0.00 1 global constructors keyed to _ZN9GridScene9drawLinesEP8QPainterR15QVarLengthArr ayI6QLineFLi100EE [14]
    0.00 0.00 1/1 __static_initialization_and_destruction_0(int, int) [15]
    -----------------------------------------------
    0.00 0.00 1/1 global constructors keyed to _ZN9GridScene9drawLinesEP8QPainterR15QVarLengthArr ayI6QLineFLi100EE [14]
    [15] 0.0 0.00 0.00 1 __static_initialization_and_destruction_0(int, int) [15]
    -----------------------------------------------
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

Similar Threads

  1. Performance problems with overlapping qgraphicsitems
    By brjames in forum Qt Programming
    Replies: 13
    Last Post: 4th May 2008, 21:42
  2. QT GraphicsView Help
    By mistertoony in forum Qt Programming
    Replies: 15
    Last Post: 15th February 2007, 04:17
  3. Replies: 1
    Last Post: 4th October 2006, 16:05
  4. QT4 Plugins - problems, problems
    By NormanDunbar in forum Qt Programming
    Replies: 6
    Last Post: 9th May 2006, 15:39
  5. Increasing performance from Qtextedit, listview, etc?
    By taylor34 in forum Qt Programming
    Replies: 1
    Last Post: 16th February 2006, 10:20

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.