Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-27365

Poor QTextLayout performance with Core Text engine

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Out of scope
    • Icon: P2: Important P2: Important
    • None
    • 4.8.2
    • GUI: Text handling
    • None

      QTextLayout's performance is much worse with the Core Text engine than the Freetype engine.

      Using this benchmark:

      #include <QtCore/QDebug>
      #include <QtCore/QElapsedTimer>
      #include <QtGui/QApplication>
      #include <QtGui/QTextLayout>
      
      static QString dummyText = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum";
      
      void layoutText(const QFont& font, const QString& text, const QSize size)
      {
          QTextLayout layout(text, font);
          layout.beginLayout();
          while (true) {
              QTextLine line = layout.createLine();
              if (!line.isValid()) {
                  break;
              }
              line.setLineWidth(size.width());
          }
          layout.endLayout();
      }
      
      int main(int argc, char** argv)
      {
          QApplication app(argc, argv);
      
          int iterations = 10000;
          QFont font = QApplication::font();
          QSize size = QSize(100, 300);
      
          QElapsedTimer timer;
          timer.start();
      
          for (int i=0; i < iterations; i++) {
              layoutText(font, dummyText, size);
          }
      
          qreal elapsedMs = timer.nsecsElapsed() / (1000 * 1000.0);
      
          qDebug() << "Layout time for" << iterations << "iterations: " << elapsedMs;
      
          return 0;
      }
      

      I get a runtime of ~11,000ms on my iMac. On an Ubuntu 12.04 VM on the same system with the same version of Qt, the runtime is about ~2,700ms.

      A profile created with Activity Monitor shows that most the of cost when using the Core Text backend is in QCoreTextFontEngine::boundingBox(glyphId), which looks as though it is doing much more work than it should be:

          +   2562 main  (in text-render-perf) + 101  [0x100002385]
          +     2538 layoutText(QFont const&, QString const&, QSize)  (in text-render-perf) + 98  [0x1000022b2]
          +     ! 1761 QTextLine::layout_helper(int)  (in QtGui) + 1339  [0x1002a397d]
          +     ! : 1754 QFontEngine::getGlyphBearings(unsigned int, double*, double*)  (in QtGui) + 35  [0x100265b23]
          +     ! : | 1575 QCoreTextFontEngine::boundingBox(unsigned int)  (in QtGui) + 86  [0x10004a496]
          +     ! : | + 1546 CTFontGetBoundingRectsForGlyphs  (in CoreText) + 202  [0x7fff8b0c1862]
          +     ! : | + ! 1195 TFont::GetBoundingBoxesForGlyphs(unsigned short const*, CGRect*, long, CTFontOrientation) const  (in CoreText) + 58  [0x7fff8b0c1bac]
          +     ! : | + ! : 683 TBaseFont::CopyParserFont() const  (in CoreText) + 128  [0x7fff8b0c3d3c]
          +     ! : | + ! : | 313 FPFontCreateFontsWithPath  (in libFontParser.dylib) + 309  [0x7fff8b230bbb]
          +     ! : | + ! : | + 148 TFPFont::TFPFont(TFont const*, __CFString const*)  (in libFontParser.dylib) + 138  [0x7fff8b235824]
          +     ! : | + ! : | + ! 111 TSFNTFont::GetPostscriptName() const  (in libFontParser.dylib) + 40  [0x7fff8b2340ea]
          +     ! : | + ! : | + ! : 91 TnameTable::GetPostscriptName() const  (in libFontParser.dylib) + 54  [0x7fff8b234446]
          +     ! : | + ! : | + ! : | 61 TnameTable::FindName(unsigned short, unsigned short, unsigned short, unsigned short) const  (in libFontParser.dylib) + 259,268,...  [0x7fff8b234681,0x7fff8b23468a,...]
          +     ! : | + ! : | + ! : | 14 TnameTable::FindName(unsigned short, unsigned short, unsigned short, unsigned short) const  (in libFontParser.dylib) + 120  [0x7fff8b2345f6]
          +     ! : | + ! : | + ! : | + 11 TsfntTable::GetTableEnd() const  (in libFontParser.dylib) + 39  [0x7fff8b234ad1]
          +     ! : | + ! : | + ! : | + ! 5 TSFNTFont::GetFontDataEndP(unsigned long*) const  (in libFontParser.dylib) + 183  [0x7fff8b234bb1]
          +     ! : | + ! : | + ! : | + ! : 3 TDataReference::DucRefCount() const  (in libFontParser.dylib) + 30  [0x7fff8b233c94]
          +     ! : | + ! : | + ! : | + ! : | 2 MReferenceCounted::RemoveReference() const  (in libFontParser.dylib) + 0  [0x7fff8b23382
      

      In contrast, a callgrind profile on the Ubuntu 12.04 VM shows that most of the work is in QTextEngine::shapeText() where I'd expect it to be.

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            esabraha Eskil Abrahamsen Blomfeldt
            robertknight Robert Knight
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes