Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QVariant conversions (.toString() .toInt()) performance.
Qt 6.12 LTS is out! See what's new in the release blog

QVariant conversions (.toString() .toInt()) performance.

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 4 Posters 6.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Mike Fidel

    Greetings.

    I wanted to ask if there is a significant performance overhead when using `QVariant' conversion methods. For example if there is a significant difference in performance when using:

    QVariant var = QVariant("MyString");
    
    qDebug() << var.toString();
    
    

    Versus

    QString str = "MyString";
    
    qDebug() << str;
    

    I'm more interested in the performance impact of the conversion operation .toString() , .toInt() etc than the object instantiation.

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #2

    @Mike-Fidel You could write a simple benchmark to measure the difference.
    I think var.toString() will be slower as it creates a new QString instance each time it is called.

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    4
    • M Offline
      M Offline
      Mike Fidel
      wrote on last edited by Mike Fidel
      #3

      @jsulm This is the benchmark I did:

      int main(int argc, char *argv[])
      {
          QElapsedTimer variantTimer;
          QElapsedTimer stringTimer;
      
          QVariant var = QVariant("My String");
      
          QString string = "My String";
      
      
      
          QString stringTest;
          QString varTest;
      
      
          stringTimer.start();
          for (int i = 0 ; i < 100000 ; i++)
          {
                stringTest = string;
          }
      
          std::cout << "string  took " << stringTimer.nsecsElapsed() << " nano seconds " << std::endl;
      
      
      
          variantTimer.start();
          for (int i = 0 ; i < 100000 ; i++)
          {
              varTest = var.toString();
          }
      
          std::cout << "Variant took " << variantTimer.nsecsElapsed() << " nano seconds " << std::endl;
      
      
      }
      

      Output I got:

      string took 2084675 nano seconds
      Variant took 4343839 nano seconds

      However if you include the deceleration of QString inside the loop like so:

      int main(int argc, char *argv[])
      {
          QElapsedTimer variantTimer;
          QElapsedTimer stringTimer;
      
          QVariant var = QVariant("My String");
      
          QString string = "My String";
      
      
      
          //QString stringTest;
          //QString varTest;
      
      
          stringTimer.start();
          for (int i = 0 ; i < 100000 ; i++)
          {
                QString stringTest = string;
          }
      
          std::cout << "string  took " << stringTimer.nsecsElapsed() << " nano seconds " << std::endl;
      
      
      
          variantTimer.start();
          for (int i = 0 ; i < 100000 ; i++)
          {
              QString varTest = var.toString();
          }
      
          std::cout << "Variant took " << variantTimer.nsecsElapsed() << " nano seconds " << std::endl;
      
      
      }
      
      
      

      I get the following output:

      string took 4607827 nano seconds
      Variant took 2628095 nano seconds

      This confuses me. It seems that Variant is quicker if you declare the variable inside the loop.

      Also the conclusion I draw from this is that performance impact of the conversion methods are largely negligible. And if your implementation requires that you use an definition with the .toString() conversion(Such as QString x = myVar.toString()), you are better off using QVariant.

      jsulmJ 1 Reply Last reply
      0
      • M Mike Fidel

        @jsulm This is the benchmark I did:

        int main(int argc, char *argv[])
        {
            QElapsedTimer variantTimer;
            QElapsedTimer stringTimer;
        
            QVariant var = QVariant("My String");
        
            QString string = "My String";
        
        
        
            QString stringTest;
            QString varTest;
        
        
            stringTimer.start();
            for (int i = 0 ; i < 100000 ; i++)
            {
                  stringTest = string;
            }
        
            std::cout << "string  took " << stringTimer.nsecsElapsed() << " nano seconds " << std::endl;
        
        
        
            variantTimer.start();
            for (int i = 0 ; i < 100000 ; i++)
            {
                varTest = var.toString();
            }
        
            std::cout << "Variant took " << variantTimer.nsecsElapsed() << " nano seconds " << std::endl;
        
        
        }
        

        Output I got:

        string took 2084675 nano seconds
        Variant took 4343839 nano seconds

        However if you include the deceleration of QString inside the loop like so:

        int main(int argc, char *argv[])
        {
            QElapsedTimer variantTimer;
            QElapsedTimer stringTimer;
        
            QVariant var = QVariant("My String");
        
            QString string = "My String";
        
        
        
            //QString stringTest;
            //QString varTest;
        
        
            stringTimer.start();
            for (int i = 0 ; i < 100000 ; i++)
            {
                  QString stringTest = string;
            }
        
            std::cout << "string  took " << stringTimer.nsecsElapsed() << " nano seconds " << std::endl;
        
        
        
            variantTimer.start();
            for (int i = 0 ; i < 100000 ; i++)
            {
                QString varTest = var.toString();
            }
        
            std::cout << "Variant took " << variantTimer.nsecsElapsed() << " nano seconds " << std::endl;
        
        
        }
        
        
        

        I get the following output:

        string took 4607827 nano seconds
        Variant took 2628095 nano seconds

        This confuses me. It seems that Variant is quicker if you declare the variable inside the loop.

        Also the conclusion I draw from this is that performance impact of the conversion methods are largely negligible. And if your implementation requires that you use an definition with the .toString() conversion(Such as QString x = myVar.toString()), you are better off using QVariant.

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #4

        @Mike-Fidel Probably I was wrong: QVariant already contains a QString

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        M 1 Reply Last reply
        1
        • J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by J.Hilk
          #5

          Isn't QString and QVariant each Implicitly Shared ?

          that means

          for (int i = 0 ; i < 100000 ; i++)
              {
                    stringTest = string;
              }
          

          does basicaly nothing? Decrese and Increase of shared pointer count

          where as

           for (int i = 0 ; i < 100000 ; i++)
              {
                  varTest = var.toString();
              }
          

          is an actual convertion => Construction of a QString and copy of data(from Qvariant)?


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          5
          • jsulmJ jsulm

            @Mike-Fidel Probably I was wrong: QVariant already contains a QString

            M Offline
            M Offline
            Mike Fidel
            wrote on last edited by
            #6

            @jsulm said in QVariant conversions (.toString() .toInt()) performance.:

            @Mike-Fidel Probably I was wrong: QVariant already contains a QString

            So QVariant might be faster, but costs more memory?

            jsulmJ 1 Reply Last reply
            0
            • M Mike Fidel

              @jsulm said in QVariant conversions (.toString() .toInt()) performance.:

              @Mike-Fidel Probably I was wrong: QVariant already contains a QString

              So QVariant might be faster, but costs more memory?

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #7

              @Mike-Fidel It should not cost more memory because of implicit sharing as @J-Hilk mentioned.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              M 1 Reply Last reply
              0
              • jsulmJ jsulm

                @Mike-Fidel It should not cost more memory because of implicit sharing as @J-Hilk mentioned.

                M Offline
                M Offline
                Mike Fidel
                wrote on last edited by
                #8

                @jsulm said in QVariant conversions (.toString() .toInt()) performance.:

                @Mike-Fidel It should not cost more memory because of implicit sharing as @J-Hilk mentioned.

                Could you elaborate? As far as I understand "Implicit Sharing" means that on assignment a pointer is passed, and only on write a copy occurs.

                So in

                for (int i = 0 ; i < 100000 ; i++)
                    {
                          stringTest = string;
                    }
                

                And in

                 for (int i = 0 ; i < 100000 ; i++)
                    {
                        varTest = var.toString();
                    }
                

                The memory fingerprint of 'varTest' and 'stringTest' should be the same. But you said that QVariant already contains a QString, shouldn't it take up more memory?

                Also How does implicit sharing explains QVariant being faster when the deceleration is made inside the loop?

                jsulmJ 1 Reply Last reply
                0
                • M Mike Fidel

                  @jsulm said in QVariant conversions (.toString() .toInt()) performance.:

                  @Mike-Fidel It should not cost more memory because of implicit sharing as @J-Hilk mentioned.

                  Could you elaborate? As far as I understand "Implicit Sharing" means that on assignment a pointer is passed, and only on write a copy occurs.

                  So in

                  for (int i = 0 ; i < 100000 ; i++)
                      {
                            stringTest = string;
                      }
                  

                  And in

                   for (int i = 0 ; i < 100000 ; i++)
                      {
                          varTest = var.toString();
                      }
                  

                  The memory fingerprint of 'varTest' and 'stringTest' should be the same. But you said that QVariant already contains a QString, shouldn't it take up more memory?

                  Also How does implicit sharing explains QVariant being faster when the deceleration is made inside the loop?

                  jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on last edited by
                  #9

                  @Mike-Fidel QString uses implicit sharing as well. So, assigning a string to another one does not increase memory usage significantly.
                  Is it

                  QString varTest;
                  for (int i = 0 ; i < 100000 ; i++)
                  {
                      varTest = var.toString();
                  }
                  

                  or

                  for (int i = 0 ; i < 100000 ; i++)
                  {
                      QString varTest = var.toString();
                  }
                  

                  ?

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  M 1 Reply Last reply
                  0
                  • jsulmJ jsulm

                    @Mike-Fidel QString uses implicit sharing as well. So, assigning a string to another one does not increase memory usage significantly.
                    Is it

                    QString varTest;
                    for (int i = 0 ; i < 100000 ; i++)
                    {
                        varTest = var.toString();
                    }
                    

                    or

                    for (int i = 0 ; i < 100000 ; i++)
                    {
                        QString varTest = var.toString();
                    }
                    

                    ?

                    M Offline
                    M Offline
                    Mike Fidel
                    wrote on last edited by
                    #10

                    @jsulm

                    QString uses implicit sharing as well. So, assigning a string to another one does not increase memory usage significantly.

                    Yes I understand, However I'm confused by what you said that QVariant already contains QString. Because if it does, shouldn't it take up more memory than just QString ? Because QVaraint is QString and something else ?

                    JonBJ 1 Reply Last reply
                    0
                    • M Mike Fidel

                      @jsulm

                      QString uses implicit sharing as well. So, assigning a string to another one does not increase memory usage significantly.

                      Yes I understand, However I'm confused by what you said that QVariant already contains QString. Because if it does, shouldn't it take up more memory than just QString ? Because QVaraint is QString and something else ?

                      JonBJ Online
                      JonBJ Online
                      JonB
                      wrote on last edited by JonB
                      #11

                      @Mike-Fidel
                      @jsulm did use the word "significantly". I don't know whether someone is saying the whole of a QVariant is shared or just its content, but if it's the latter, yes, a QVaraint is a QString and something else, but the "something else" is relatively small, at least compared to, say, an "average" 42-byte string.

                      M 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @Mike-Fidel
                        @jsulm did use the word "significantly". I don't know whether someone is saying the whole of a QVariant is shared or just its content, but if it's the latter, yes, a QVaraint is a QString and something else, but the "something else" is relatively small, at least compared to, say, an "average" 42-byte string.

                        M Offline
                        M Offline
                        Mike Fidel
                        wrote on last edited by
                        #12

                        @JonB Got it, Thanks!

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt
                        • Unsolved