Qt 5.6.1 QPainter::setFont() benchmark - please help and join
-
With Qt 5.6.0 and later I noticed a significant performance breakdown when changing fonts during multiple QPainter::drawText() calls. But I'm not sure if this is Qt related or related to my hardware.
It would be a great help if some of you can run the following short example code and give a little feadback about the results on their hardware here. The example code should be run with Qt 5.6.0 or later or Qt 5.5.1 or prior versions.
The provided example code (see below) runs on my machine:
QT 5.5.1 x64 VS_2013:
Debug
Test1 ( 1 font ): 5.243 seconds
Test2 (13 fonts): 5.200 seconds
Test3 ( 4 fonts): 5.249 seconds
Test4 ( 3 fonts): 5.470 secondsRelease
Test1 ( 1 font ): 3.791 seconds
Test2 (13 fonts): 3.880 seconds
Test3 ( 4 fonts): 3.879 seconds
Test4 ( 3 fonts): 3.944 secondsQT 5.6.1-1 x64 VS_2013:
Debug
Test1 ( 1 font ): 5.291 seconds
Test2 (13 fonts): 43.682 seconds ==> slow
Test3 ( 4 fonts): 24.804 seconds ==> slow
Test4 ( 3 fonts): 5.834 secondsRelease
Test1 ( 1 font ): 3.773 seconds
Test2 (13 fonts): 20.354 seconds ==> slow
Test3 ( 4 fonts): 13.592 seconds ==> slow
Test4 ( 3 fonts): 4.009 secondsMy hardware and software specs:
Hardware:
CPU: Intel Core 2 Duo E8400 @3.00GHz
RAM: 8GB Dual Channal DDR2 @445MHz (5-5-5-15)
Graphic card: ATI Radeon HD 3600 512MB (Directx 10.1 - non Gamer card)
Harddrive: Samsung Evo Pro 850 512GBOperating System:
Windows 10 Pro 64bit Build (Version 1511 Build 10586.420)Compiler:
Visual Studio 2013 Update 5Example code:
#include <QApplication> #include <QWidget> #include <QPainter> #include <QElapsedTimer> class Widget : public QWidget { public: Widget(); protected: void timerEvent(QTimerEvent *event); void paintEvent(QPaintEvent *); private: QElapsedTimer elapsedTimer; int timerId; int elapsedTime1, elapsedTime2, elapsedTime3, elapsedTime4; bool isFinished1, isFinished2, isFinished3, isFinished4, isFinished5; int i, x1, x2, x3, x4, y1, y2, y3, y4; static QFont Arial, Caladea, Tomaha, Consolas, Calibri, Impact; static QFont Courier_New, Gorgia, Verdana, Times_New_Roman; static QFont Microsoft_Sans_Serif, Segoe_UI, Trebuchet_MS; }; QFont Widget::Arial("Arial", 14); QFont Widget::Caladea("Caladea", 14); QFont Widget::Tomaha("Tomaha", 14); QFont Widget::Consolas("Consolas", 14); QFont Widget::Calibri("Calibri", 14); QFont Widget::Impact("Impact", 14); QFont Widget::Segoe_UI("Segoe UI", 14); QFont Widget::Gorgia("Gorgia", 14); QFont Widget::Verdana("Verdana", 14); QFont Widget::Trebuchet_MS("Trebuchet MS", 14); QFont Widget::Courier_New("Courier New", 14); QFont Widget::Times_New_Roman("Times New Roman", 14); QFont Widget::Microsoft_Sans_Serif("Microsoft Sans Serif", 14); Widget::Widget() { setAutoFillBackground(true); setPalette(Qt::white); timerId = startTimer(1); elapsedTimer.start(); i=0; x1=0; x2=0, x3=0, x4=0; isFinished1 = isFinished2 = isFinished3 = isFinished4 = isFinished5 = false; } void Widget::timerEvent(QTimerEvent* /* event */) { update(); } void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); if (i > 0 && i < 800) { y1 = 10; painter.setFont(Arial); painter.drawText(x1, y1 += 30, "Test 1"); painter.drawText(x1, y1 += 30, "row 01"); painter.drawText(x1, y1 += 30, "row 02"); painter.drawText(x1, y1 += 30, "row 03"); painter.drawText(x1, y1 += 30, "row 04"); painter.drawText(x1, y1 += 30, "row 05"); painter.drawText(x1, y1 += 30, "row 06"); painter.drawText(x1, y1 += 30, "row 07"); painter.drawText(x1, y1 += 30, "row 08"); painter.drawText(x1, y1 += 30, "row 09"); painter.drawText(x1, y1 += 30, "row 10"); painter.drawText(x1, y1 += 30, "row 11"); painter.drawText(x1, y1 += 30, "row 12"); x1++; elapsedTime1 = elapsedTimer.elapsed(); } else if (i > 800 && i < 1600) { isFinished1 = true; y2 = 160; painter.setFont(Arial); painter.drawText(x2, y2 += 30, "Test 2"); painter.setFont(Caladea); painter.drawText(x2, y2 += 30, "row 01"); painter.setFont(Tomaha); painter.drawText(x2, y2 += 30, "row 02"); painter.setFont(Consolas); painter.drawText(x2, y2 += 30, "row 03"); painter.setFont(Calibri); painter.drawText(x2, y2 += 30, "row 04"); painter.setFont(Impact); painter.drawText(x2, y2 += 30, "row 05"); painter.setFont(Segoe_UI); painter.drawText(x2, y2 += 30, "row 06"); painter.setFont(Gorgia); painter.drawText(x2, y2 += 30, "row 07"); painter.setFont(Verdana); painter.drawText(x2, y2 += 30, "row 08"); painter.setFont(Trebuchet_MS); painter.drawText(x2, y2 += 30, "row 09"); painter.setFont(Courier_New); painter.drawText(x2, y2 += 30, "row 10"); painter.setFont(Times_New_Roman); painter.drawText(x2, y2 += 30, "row 11"); painter.setFont(Microsoft_Sans_Serif); painter.drawText(x2, y2 += 30, "row 12"); x2++; elapsedTime2 = elapsedTimer.elapsed(); } else if (i > 1600 && i < 2400) { isFinished2 = true; y3 = 310; painter.setFont(Arial); painter.drawText(x3, y3 += 30, "Test 3"); painter.drawText(x3, y3 += 30, "row 01"); painter.drawText(x3, y3 += 30, "row 02"); painter.drawText(x3, y3 += 30, "row 03"); painter.setFont(Consolas); painter.drawText(x3, y3 += 30, "row 04"); painter.drawText(x3, y3 += 30, "row 05"); painter.drawText(x3, y3 += 30, "row 06"); painter.setFont(Impact); painter.drawText(x3, y3 += 30, "row 07"); painter.drawText(x3, y3 += 30, "row 08"); painter.drawText(x3, y3 += 30, "row 09"); painter.setFont(Courier_New); painter.drawText(x3, y3 += 30, "row 10"); painter.drawText(x3, y3 += 30, "row 11"); painter.drawText(x3, y3 += 30, "row 12"); x3++; elapsedTime3 = elapsedTimer.elapsed(); } else if (i > 2400 && i < 3200) { isFinished3 = true; y4 = 460; painter.setFont(Arial); painter.drawText(x4, y4 += 30, "Test 4"); painter.drawText(x4, y4 += 30, "row 01"); painter.drawText(x4, y4 += 30, "row 02"); painter.drawText(x4, y4 += 30, "row 03"); painter.drawText(x4, y4 += 30, "row 04"); painter.setFont(Impact); painter.drawText(x4, y4 += 30, "row 05"); painter.drawText(x4, y4 += 30, "row 06"); painter.drawText(x4, y4 += 30, "row 07"); painter.drawText(x4, y4 += 30, "row 08"); painter.setFont(Courier_New); painter.drawText(x4, y4 += 30, "row 09"); painter.drawText(x4, y4 += 30, "row 10"); painter.drawText(x4, y4 += 30, "row 11"); painter.drawText(x4, y4 += 30, "row 12"); x4++; elapsedTime4 = elapsedTimer.elapsed(); } else if (i > 3200) { isFinished4 = true; } i++; if (isFinished1) { painter.setFont(QFont("Arial", 12.0, QFont::Bold)); painter.drawText(QPoint(200, 100), "Test1 (1 font) elapsed time in seconds: " + QString::number(elapsedTime1/1000.0)); } if (isFinished2) { painter.drawText(QPoint(200, 200), "Test2 (12 fonts) elapsed time in seconds: " + QString::number((elapsedTime2-elapsedTime1)/1000.0)); } if (isFinished3) { painter.drawText(QPoint(200, 300), "Test3 (4 fonts) elapsed time in seconds: " + QString::number((elapsedTime3-elapsedTime2)/1000.0)); } if (isFinished4) { painter.drawText(QPoint(200, 400), "Test4 (3 fonts) elapsed time in seconds: " + QString::number((elapsedTime4-elapsedTime3)/1000.0)); } } int main(int argc, char *argv[]) { QApplication app(argc, argv); Widget widget; widget.showMaximized(); return app.exec(); }
-
-
-
-
Hi,
Can you check it's still the case with 5.7.0 ?
In any case, you should check the bug report system to see if it's something known. If not please consider creating a new report providing your benchmark application.
-
-
mrjj and thEClaw thank you very much for contributing your results here. That is very helpfull!
It seams the problem is only related to Windows operating systems, because thEClaws results on Linux are fine. Linux does freetype font rendering, Windows not - that might be the reason.
The hardware might also affect the issue. Because on my 7 year old machine with slow graphics card the test with 3 fonts and 4 fonts did already slow down. Whereas mrjjs results on Windows 7 are still fine with Qt 5.6.0 and Qt 5.7.0 in that case.
mrjj is on Windows 7 and I'm on Windows 10 so there is another difference.
Would be great if another one on Windows could contribute his Qt 5.6.0 or later results here to find out.
-
Qt 5.7.0 x86 Release VS 2015 U2, Win 8.1 x64, i7-4770 using internal Intel graphics
1920x1200 primary Display
Test1 3.356
Test2 13.741
Test3 2.921
Test4 2.9313840x2160 secondary Display
Test1 13.568
Test2 20.904
Test3 18.167
Test4 13.397 -
MarkusR,
many thanks for your (propably release version) results. They also show the slow down (Test2 = 12 times font switching): If fonts are changed often.
-
The slow down happens also using just 1 font and switching different sizes of it.
But if only two sizes of the same font are used - switching its size alternating in every row with setFont() - there is no slow down (see last test in the code below).
So the problem may not be only QPainter::setFont related. But there is probably some font cache / memory managment issue involved too.Here is my benchmark of the new example code below:
QT 5.7.0_x64 VS_2013 Debug
Arial font, 4 sizes, seconds 4.860
Arial font, 6 sizes, seconds 34.763
Arial font, 8 sizes, seconds 40.807
Arial font, 12 sizes, seconds 46.776
Arial font, 2 sizes alternating, seconds 5.686QT 5.7.0_x64 VS_2013 Release
Arial font, 4 sizes, seconds 3.799
Arial font, 6 sizes, seconds 19.368
Arial font, 8 sizes, seconds 22.037
Arial font, 12 sizes, seconds 24.620
Arial font, 2 sizes alternating, seconds 4.01New example code with only 1 font:
#include <QApplication> #include <QWidget> #include <QPainter> #include <QElapsedTimer> class Widget : public QWidget { public: Widget(); protected: void timerEvent(QTimerEvent *event); void paintEvent(QPaintEvent *); private: QElapsedTimer elapsedTimer; int timerId; int elapsedTime1, elapsedTime2, elapsedTime3, elapsedTime4, elapsedTime5; bool isFinished1, isFinished2, isFinished3, isFinished4, isFinished5, isFinished6; int i, x1, x2, x3, x4, x5, y1, y2, y3, y4, y5; static QFont Arial7, Arial8, Arial9, Arial10, Arial11, Arial12; static QFont Arial13, Arial14, Arial15, Arial16, Arial17, Arial18; }; QFont Widget::Arial7("Arial", 7); QFont Widget::Arial8("Arial", 8); QFont Widget::Arial9("Arial", 9); QFont Widget::Arial10("Arial", 10); QFont Widget::Arial11("Arial", 11); QFont Widget::Arial12("Arial", 12); QFont Widget::Arial13("Arial", 13); QFont Widget::Arial14("Arial", 14); QFont Widget::Arial15("Arial", 15); QFont Widget::Arial16("Arial", 16); QFont Widget::Arial17("Arial", 17); QFont Widget::Arial18("Arial", 18); Widget::Widget() { setAutoFillBackground(true); setPalette(Qt::white); timerId = startTimer(1); elapsedTimer.start(); i=0; x1=0; x2=0, x3=0, x4=0, x5=0; isFinished1 = isFinished2 = isFinished3 = false; isFinished4 = isFinished5 = isFinished6 = false; } void Widget::timerEvent(QTimerEvent* /* event */) { update(); } void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); if (i > 0 && i < 800) { y1 = 10; painter.setFont(Arial18); painter.drawText(x1, y1 += 30, "Arial 4 sizes"); painter.drawText(x1, y1 += 30, "row 01"); painter.drawText(x1, y1 += 30, "row 02"); painter.drawText(x1, y1 += 30, "row 03"); painter.setFont(Arial10); painter.drawText(x1, y1 += 30, "row 04"); painter.drawText(x1, y1 += 30, "row 05"); painter.drawText(x1, y1 += 30, "row 06"); painter.setFont(Arial12); painter.drawText(x1, y1 += 30, "row 07"); painter.drawText(x1, y1 += 30, "row 08"); painter.drawText(x1, y1 += 30, "row 09"); painter.setFont(Arial14); painter.drawText(x1, y1 += 30, "row 10"); painter.drawText(x1, y1 += 30, "row 11"); painter.drawText(x1, y1 += 30, "row 12"); x1++; elapsedTime1 = elapsedTimer.elapsed(); } else if (i > 800 && i < 1600) { isFinished1 = true; y2 = 110; painter.setFont(Arial18); painter.drawText(x2, y2 += 30, "Arial font 6 sizes"); painter.drawText(x2, y2 += 30, "row 01"); painter.drawText(x2, y2 += 30, "row 02"); painter.setFont(Arial8); painter.drawText(x2, y2 += 30, "row 03"); painter.drawText(x2, y2 += 30, "row 04"); painter.setFont(Arial10); painter.drawText(x2, y2 += 30, "row 05"); painter.drawText(x2, y2 += 30, "row 06"); painter.setFont(Arial12); painter.drawText(x2, y2 += 30, "row 07"); painter.drawText(x2, y2 += 30, "row 08"); painter.setFont(Arial14); painter.drawText(x2, y2 += 30, "row 09"); painter.drawText(x2, y2 += 30, "row 10"); painter.setFont(Arial16); painter.drawText(x2, y2 += 30, "row 11"); painter.drawText(x2, y2 += 30, "row 12"); x2++; elapsedTime2 = elapsedTimer.elapsed(); } else if (i > 1600 && i < 2400) { isFinished2 = true; y3 = 210; painter.setFont(Arial18); painter.drawText(x3, y3 += 30, "Arial 8 sizes"); painter.setFont(Arial9); painter.drawText(x3, y3 += 30, "row 01"); painter.drawText(x3, y3 += 30, "row 02"); painter.setFont(Arial10); painter.drawText(x3, y3 += 30, "row 03"); painter.setFont(Arial11); painter.drawText(x3, y3 += 30, "row 04"); painter.drawText(x3, y3 += 30, "row 05"); painter.setFont(Arial12); painter.drawText(x3, y3 += 30, "row 06"); painter.drawText(x3, y3 += 30, "row 07"); painter.setFont(Arial13); painter.drawText(x3, y3 += 30, "row 08"); painter.drawText(x3, y3 += 30, "row 09"); painter.setFont(Arial14); painter.drawText(x3, y3 += 30, "row 10"); painter.drawText(x3, y3 += 30, "row 11"); painter.setFont(Arial15); painter.drawText(x3, y3 += 30, "row 12"); x3++; elapsedTime3 = elapsedTimer.elapsed(); } else if (i > 2400 && i < 3200) { isFinished3 = true; y4 = 310; painter.setFont(Arial18); painter.drawText(x4, y4 += 30, "Arial 12 sizes"); painter.setFont(Arial8); painter.drawText(x4, y4 += 30, "row 02"); painter.setFont(Arial9); painter.drawText(x4, y4 += 30, "row 03"); painter.setFont(Arial10); painter.drawText(x4, y4 += 30, "row 04"); painter.setFont(Arial11); painter.drawText(x4, y4 += 30, "row 05"); painter.setFont(Arial12); painter.drawText(x4, y4 += 30, "row 06"); painter.setFont(Arial13); painter.drawText(x4, y4 += 30, "row 07"); painter.setFont(Arial14); painter.drawText(x4, y4 += 30, "row 08"); painter.setFont(Arial15); painter.drawText(x4, y4 += 30, "row 09"); painter.setFont(Arial16); painter.drawText(x4, y4 += 30, "row 10"); painter.setFont(Arial17); painter.drawText(x4, y4 += 30, "row 11"); painter.setFont(Arial18); painter.drawText(x4, y4 += 30, "row 12"); x4++; elapsedTime4 = elapsedTimer.elapsed(); } else if (i > 3200 && i < 4000) { isFinished4 = true; y5 = 410; painter.setFont(Arial18); painter.drawText(x5, y5 += 30, "Arial 12 sizes"); painter.setFont(Arial10); painter.drawText(x5, y5 += 30, "row 02"); painter.setFont(Arial18); painter.drawText(x5, y5 += 30, "row 03"); painter.setFont(Arial10); painter.drawText(x5, y5 += 30, "row 04"); painter.setFont(Arial18); painter.drawText(x5, y5 += 30, "row 05"); painter.setFont(Arial10); painter.drawText(x5, y5 += 30, "row 06"); painter.setFont(Arial18); painter.drawText(x5, y5 += 30, "row 07"); painter.setFont(Arial10); painter.drawText(x5, y5 += 30, "row 08"); painter.setFont(Arial18); painter.drawText(x5, y5 += 30, "row 09"); painter.setFont(Arial10); painter.drawText(x5, y5 += 30, "row 10"); painter.setFont(Arial18); painter.drawText(x5, y5 += 30, "row 11"); painter.setFont(Arial10); painter.drawText(x5, y5 += 30, "row 12"); x5++; elapsedTime5 = elapsedTimer.elapsed(); } else if (i > 4000) { isFinished5 = true; } i++; if (isFinished1) { painter.setFont(QFont("Arial", 12.0, QFont::Bold)); painter.drawText(QPoint(200, 50), "Arial font: 4 sizes, seconds: " + QString::number(elapsedTime1/1000.0)); } if (isFinished2) { painter.drawText(QPoint(200, 100), "Arial font: 6 sizes, seconds: " + QString::number((elapsedTime2-elapsedTime1)/1000.0)); } if (isFinished3) { painter.drawText(QPoint(200, 150), "Arial font: 8 sizes, seconds: " + QString::number((elapsedTime3-elapsedTime2)/1000.0)); } if (isFinished4) { painter.drawText(QPoint(200, 200), "Arial font: 12 sizes, seconds: " + QString::number((elapsedTime4-elapsedTime3)/1000.0)); } if (isFinished5) { painter.drawText(QPoint(200, 250), "Arial font: 2 sizes alternating, seconds: " + QString::number((elapsedTime5-elapsedTime4)/1000.0)); } } int main(int argc, char *argv[]) { QApplication app(argc, argv); Widget widget; widget.showMaximized(); return app.exec(); }
-
This is the related Qt Bug report:
https://bugreports.qt.io/browse/QTBUG-54180 -
@mireiner
Thank you.
7/12