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

Accessing a QVariantMap/QVariantList is very slow in QML

    XMLWordPrintable

Details

    • 752cd2aca42f6625f1cfc364937e0d39828cf954

    Description

      Accessing a QVariantMap/QVariantList is very slow in QML.
      This applies to every single QVariantMap/QVariantList acess, even if it is the same access. Around 150 ms on ARM9 200MHz.

      Accessing a QList<QObject*> is 15 times faster on a ARM9.

      Of course, a QList is accessed by indexes and QVariantMap by "string indexes". I could reach an even better access time with "string indexes" by associating a "QHash<QString, int> m_prgVarCode2Idx" and a "QList<QObject > m_sublist". This is 15 times faster than accessing a QList<QObject> and 30 times faster than accessing a QVariantMap:

          Q_INVOKABLE QObject* getParameterFromCode(QString code)
          {
              QObject *retval = NULL;
              if (m_prgVarCode2Idx.contains(code))
                  retval = m_sublist.at(m_prgVarCode2Idx.value(code));
      
              return retval;
          }
      

      Let's consider this code

      #ifndef PARAMETERTEST_H
      #define PARAMETERTEST_H
      
      #include <QtDeclarative>
      #include <QObject>
      
      class ParameterCode: public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QString code READ code WRITE setCode NOTIFY notifyChanged);
      public:
          ParameterCode(QString & code):m_code(code){};
          QString &code()
          {
              return m_code;
          }
          void setCode(QString code) {
              m_code = code;
              emit notifyChanged();
          }
      
      signals:
              void notifyChanged();
      private:
              QString m_code;
      };
      
      class ParameterTest : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QList<QObject*> sublist READ sublist NOTIFY parametersNotifyChanged)
          Q_PROPERTY(QVariantList vsubparams READ vsubparams NOTIFY parametersNotifyChanged)
          Q_PROPERTY(QVariantMap variantMapParameters READ variantMapParameters NOTIFY parametersNotifyChanged);
      public:
          ParameterTest()
          {
              for (int i = 0; i < 500; i++)
              {
                  QString code("TESTCODE");
                  code += QString::number(i);
                  m_prgVarCode2Idx[code] = i;
                  ParameterCode *newParameter = new ParameterCode(code);
                  m_vsubparams.append(QVariant::fromValue((QObject*)newParameter));
                  m_vProgramParameters[code] = QVariant::fromValue((QObject*)newParameter);
                  m_sublist.append((QObject*)newParameter);
              }
          }
      
      
          Q_INVOKABLE QObject* getParameterFromCode(QString code)
          {
              QObject *retval = NULL;
              if (m_prgVarCode2Idx.contains(code))
                  retval = m_sublist.at(m_prgVarCode2Idx.value(code));
      
              return retval;
          }
      
          QVariantList & vsubparams() {
              return m_vsubparams;
          }
      
          QVariantMap & variantMapParameters()
          {
              return m_vProgramParameters;
          }
      
          QList<QObject*> & sublist() {
              return m_sublist;
          }
      
      signals:
          void parametersNotifyChanged();
      private:
          QVariantMap m_vProgramParameters;
          QVariantList m_vsubparams;
          QList<QObject*> m_sublist;
          QHash<QString, int> m_prgVarCode2Idx;
      };
      
      #endif // PARAMETERTEST_H
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
      
          QDeclarativeView *mHomeView = new QDeclarativeView();
          QDeclarativeContext *context = mHomeView->rootContext();
          context->setContextProperty("parametertest", new ParameterTest());
          mHomeView->setSource(QUrl("qrc:/programSelectionPage.qml"));
          mHomeView->show();
      
          return a.exec();
      }
      
      import QtQuick 1.0
      
      Item {
          width: 320
          height: 240
          focus: true
      
          function test_1() //around 150 msecs per access on arm
          {
              var inittime =  new Date();
              var val;
              for (var i = 0; i < 10; i++)
                  val = parametertest.variantMapParameters["TESTCODE50"].code;
              var duration = new Date() - inittime;
              console.log("1--parameter value:"+ val)
              console.log(" called in "+duration+" msecs. ");
          }
          function test_2() //around 150 msecs per access on arm
          {
              var inittime =  new Date();
              var val;
              for (var i = 0; i < 10; i++)
                  val = parametertest.variantMapParameters.TESTCODE50.code;
              var duration = new Date() - inittime;
              console.log("2--parameter value:"+ val);
              console.log(" called in "+duration+" msecs. ");
          }
          function test_3() //around 125 msecs per access on arm
          {
              var inittime =  new Date();
              var val;
              for (var i = 0; i < 10; i++)
                  val = parametertest.vsubparams[50].code;
              var duration = new Date() - inittime;
              console.log("3--parameter value:"+ val);
              console.log(" called in "+duration+" msecs. ");
          }
          function test_4() //around 9 msecs per access on arm
          {
              var inittime =  new Date();
              var val;
              for (var i = 0; i < 100; i++)
                  val = parametertest.sublist[50].code;
              var duration = new Date() - inittime;
              console.log("4--parameter value:"+ val);
              console.log(" called in "+duration+" msecs. ");
          }
          function test_5() //around 0.6 msecs per access on arm
          {
              var inittime =  new Date();
              for (var i = 0; i < 100; i++)
                  var val = parametertest.getParameterFromCode("TESTCODE50").code;
              var duration = new Date() - inittime;
              console.log("5--parameter value:"+ val);
              console.log(" called in "+duration+" msecs. ");
          }
      
      
          Keys.onPressed:{
              test_1();
              test_2();
              test_3();
              test_4();
              test_5();
          }
      }
      

      On a PC:

      1--parameter value:TESTCODE50
       called in 187 msecs. 
      2--parameter value:TESTCODE50
       called in 197 msecs. 
      3--parameter value:TESTCODE50
       called in 68 msecs. 
      4--parameter value:TESTCODE50
       called in 31 msecs. 
      5--parameter value:TESTCODE50
       called in 4 msecs. 
      

      On a ARM9 200MHz:

      1--parameter value:TESTCODE50                                                   
       called in 1439 msecs.                                                          
      2--parameter value:TESTCODE50                                                   
       called in 1510 msecs.                                                          
      3--parameter value:TESTCODE50                                                   
       called in 1263 msecs.                                                          
      4--parameter value:TESTCODE50                                                   
       called in 956 msecs.                                                           
      5--parameter value:TESTCODE50                                                   
       called in 57 msecs.
      

      Why is it so slow with a QVariantMap ? It seems the hash table between "string indexes" and indexes are constructed at every single access.

      Attachments

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

        Activity

          People

            chriadam Christopher Adams (closed Nokia identity) (Inactive)
            agroyer Anthony Groyer
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes