Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QT code slower than java file for processing.
Forum Updated to NodeBB v4.3 + New Features

QT code slower than java file for processing.

Scheduled Pinned Locked Moved General and Desktop
15 Posts 4 Posters 4.4k Views 4 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 Offline
    M Offline
    mcosta
    wrote on last edited by
    #6

    As I said, the best way to find bottlenecks is to use some profiling tool

    Once your problem is solved don't forget to:

    • Mark the thread as SOLVED using the Topic Tool menu
    • Vote up the answer(s) that helped you to solve the issue

    You can embed images using (http://imgur.com/) or (http://postimage.org/)

    1 Reply Last reply
    0
    • N Offline
      N Offline
      nurtan
      wrote on last edited by
      #7

      I have changed from QString to QByteArray and has improved a lot, in the application of test, time has gone down to 350 milliseconds, making it as fast as java. But when I bring changes to the real application, time went down from f 2300 milliseconds to 1300 milliseconds but still far from 350 milliseconds that it takes for the test application.
      I'm looking for a profiler to see what is going on.

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mcosta
        wrote on last edited by
        #8

        Sorry I can't help you but I think you can find something using Gooogle

        Once your problem is solved don't forget to:

        • Mark the thread as SOLVED using the Topic Tool menu
        • Vote up the answer(s) that helped you to solve the issue

        You can embed images using (http://imgur.com/) or (http://postimage.org/)

        1 Reply Last reply
        0
        • H Offline
          H Offline
          Huulivoide
          wrote on last edited by
          #9

          Why are you storing the values as strings in the class?
          You should use references when taking stuff in, to avoid an extra allocation
          on each function call, also you code is not const correct, fixing that might
          help the compiler optimize your code better.

          1 Reply Last reply
          0
          • N Offline
            N Offline
            nurtan
            wrote on last edited by
            #10

            With references do you mean to use QStringRef, why my code is not const correct, could you give me an example?

            Thank you.

            H 1 Reply Last reply
            0
            • N nurtan

              With references do you mean to use QStringRef, why my code is not const correct, could you give me an example?

              Thank you.

              H Offline
              H Offline
              Huulivoide
              wrote on last edited by Huulivoide
              #11

              @nurtan

              No with references I mean reference void myFunc(QString& str)
              with const-correctness I mean that none of your functions or the parameters
              they take in are marked const, even tough they are const.

              I take it you are not very familiar with C++, you should learn C++ properly
              before using Qt. C++ can be used to make efficient programs if one knows
              his way around C++, but if he doesn't things will go wrong.

              Your code clearly shows you have now idea about the differences of pointer
              and value types, as you are doing to "null-pointer" check on variables that
              can never contain null-pointers.

              http://www.cprogramming.com/tutorial/references.html
              https://isocpp.org/wiki/faq/const-correctness

              /* Example of a good function
              / str is passed as a reference, no copy is made */
              QString myFunc(const QString& str, QPushButton* mutableButton) const
              {
                  QIcon icon(QString("/the/str/is/not/changed/so/it/is/const/") + str);
                  mutableButton->setIcon(icon);
                  // A non-const member function is called on mutableButton,
                  // that is it is being changed somehow. So it is not const
              }
              

              Also the following piece of code makes no sense.

              QString Coordenada2::getY()
              {
                  /* This reads as: If empty return a new version of empty
                     Also you should use y.isEmpty() to check if the string is empty */
                  if (y == QString::null)
                      return "";
              
                  // You can just do this. If it is empty the returned value will be same
                  // as 'return "";'
                  return y;
              }
              
              1 Reply Last reply
              0
              • M Offline
                M Offline
                mcosta
                wrote on last edited by
                #12

                to add something to @Huulivoide ; at the moment passing a QString by value is not so expensive because Qt uses Implicit Sharing (there's only a reference counter incremented)

                Once your problem is solved don't forget to:

                • Mark the thread as SOLVED using the Topic Tool menu
                • Vote up the answer(s) that helped you to solve the issue

                You can embed images using (http://imgur.com/) or (http://postimage.org/)

                1 Reply Last reply
                0
                • Chris KawaC Offline
                  Chris KawaC Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by Chris Kawa
                  #13

                  @mcosta Still, even with implicit sharing, creating a new instance, copying a data pointer and incrementing a refcount in a thread safe manner is a lot more expensive than simply passing a const reference (which is basically 0 footprint operation when an optimizer passes through). That's why passing "in" parameters as const references is always the preferred way.

                  @nurtan There are many little problems with code above. The const ref parameters are one of them but there are others.
                  For example constructing empty string via "". Empty strings should always be constructed with QString() constructor. You migt say it's the same but constructing string with "" calls QString(const char*) which requires at least some code to determine the buffer is empty (it's not as there is null terminator really).

                  Checking if string is empty by calling operator== and QString::null is also a bad idea. Whenever possible use methods like isNull or isEmpty. They might do the same but also might be more efficient, e.g. by just checking internal character count (integer comparison instead of string comparison).

                  Another big problem is storing everything as strings, even things that are evidently numbers, like x, or mantissa. String comparison is never gonna be anywhere close to what you can get with plain integers.

                  Yet another problem is when reading the file. Creating a new string each line is wasteful. Create the string once, call reserve on it with the anticipated number of characters and then reuse it. That one is small when compared to IO overhead, but it's good to get in habit of not neglecting small gains.

                  1 Reply Last reply
                  0
                  • N Offline
                    N Offline
                    nurtan
                    wrote on last edited by
                    #14

                    Today I tried to see why the execution time was different in the test application versus real application, I found an error in the code of the test application. Once the error was corrected, the time in the application of test and the real one are equal, but comparing times with java, thus are very different. Java uses 350 milliseconds but in QT, the time is 1964 milliseconds using Qstring and 1190 milliseconds using QByteArray.

                    I know the c ++ but in the last 15 years I have been programming in Java, where some things are different.

                    About your question , @Huulivoide , of why I store values as strings, it is because I need to have those values to operate them later, store, string or float does not matter because I operate both strings as float

                    I tried to pass and return by reference as you indicate and times have fallen to 1632 in the case of using QString and 1133 in the case of QByteArray, well above on java's time.

                    the getY () function that you indicate me, it is so as It is copied from java, java a null string is different than the empty string and you can not ask if a null string is empty with .isEmpty (), in QT I've noticed that .isEmpty () you can use it with a null string.

                    @Chris-Kawa, I will try what you have indicated me, the class stores the String because in subsequent processes I work with such data as strings, also as floats but I have more operations with strings than floats.

                    1 Reply Last reply
                    0
                    • N Offline
                      N Offline
                      nurtan
                      wrote on last edited by nurtan
                      #15

                      I've made the changes that you have told me, both using QString as QByteArray classes, times have improved compared to the first post, and using QByteArray has been faster than QString , so I have taken this option.

                      Coordenada.cpp

                      QByteArray &Coordenada2::getComentario() {
                          return comentario;
                      }
                      
                      
                      void Coordenada2::setComentario(const QByteArray &comentario) {
                          this->comentario = comentario;
                      }
                      
                      
                      Coordenada2::Coordenada2() {
                          x=QByteArray("0");
                          y=QByteArray("0");
                          z=QByteArray("0");
                          mantisa=QByteArray("");
                      }
                      
                      QByteArray &Coordenada2::getMantisa(){
                          return mantisa;
                      }
                      QByteArray Coordenada2::getMantisa(const QByteArray &dato) {
                              QByteArray mantisa= QByteArray("");
                              for (int x = 0; x < dato.length(); x++) {
                                  switch (dato.at(x)) {
                                      case 'G':
                                      case 'X':
                                      case 'Y':
                                      case 'Z':
                                      case 'M':
                                      case 'H':
                                      case 'R':
                                      case 'A':
                                      case 'I':
                                      case 'J':
                                      case 'K':
                                      case 'S':
                                      case 'T':
                                      case 'P':
                                      case 'F':
                                          mantisa.append(dato.at(x));
                                          mantisa.append("");
                                  }
                              }
                              return mantisa;
                      }
                      void Coordenada2::setMantisa(const QByteArray &datos) {
                          mantisa = getMantisa(datos);
                      }
                      
                      Coordenada2::Coordenada2(const QByteArray &lineacodigo) {
                          procesaLinea(lineacodigo);
                          setMantisa(lineacodigo);
                      }
                      
                      bool Coordenada2::isX() {
                          return !x.isEmpty();
                      }
                      
                      bool Coordenada2::isY() {
                          return !y.isEmpty();
                      }
                      
                      bool Coordenada2::isZ() {
                          return !z.isEmpty();
                      }
                      
                      QByteArray &Coordenada2::getX() {
                          return x;
                      }
                      
                      float Coordenada2::getNumeroX() {
                          if (x.isEmpty()) {
                              return 0;
                          }
                          return x.toFloat();
                      }
                      
                      void Coordenada2::setX(const QByteArray &x) {
                          this->x = x;
                          anadeMantisa("X");
                      }
                      
                      void Coordenada2::setX(const float &x) {
                          this->x = QByteArray(reinterpret_cast<const char *>(&x), sizeof (x));
                          anadeMantisa("X");
                      }
                      
                      QByteArray &Coordenada2::getY() {
                          return y;
                      }
                      
                      float Coordenada2::getNumeroY() {
                          if (y.isEmpty()) {
                              return 0;
                          }
                          return y.toFloat();
                      }
                      
                      void Coordenada2::setY(const QByteArray &y) {
                          this->y = y;
                          anadeMantisa("Y");
                      }
                      
                      void Coordenada2::setY(const float &y) {
                          this->y=QByteArray(reinterpret_cast<const char *>(&y), sizeof (y));
                          anadeMantisa("Y");
                      }
                      
                      QByteArray &Coordenada2::getZ() {
                          return z;
                      }
                      
                      float Coordenada2::getNumeroZ() {
                          if (z.isEmpty()) {
                              return 0;
                          }
                          return z.toFloat();
                      }
                      
                      void Coordenada2::setZ(const QByteArray &z) {
                          this->z = z;
                          anadeMantisa("Z");
                      }
                      
                      void Coordenada2::setZ(const float &z) {
                          this->z = QByteArray(reinterpret_cast<const char *>(&z), sizeof (z));
                          anadeMantisa("Z");
                      }
                      
                      void Coordenada2::anadeMantisa(const QByteArray parametro) {
                          if (mantisa.isEmpty()) {
                              mantisa = parametro;
                          }
                          if (!mantisa.contains(parametro)) {
                              mantisa.append(" ");
                              mantisa.append(parametro);
                          }
                      }
                      void Coordenada2::procesaLinea(const QByteArray &codigo) {
                          int pos = 0;
                          comentario = QByteArray("");
                          while (pos < codigo.length()) {
                              char letra = codigo.at(pos++);
                              if (pos >= codigo.length()) {
                                  if (letra == '/') {
                                      comentario = QByteArray("/");
                                  } else {
                                      comentario.append(letra);
                                  }
                                  break;
                              }
                              switch (letra) {
                                  case 'X':
                                      if (!isNumeric(codigo.at(pos)) && codigo.at(pos) != '-' && codigo.at(pos) != '+') {
                                          comentario.append(letra);
                                          break;
                                      }
                                      x=QByteArray("");
                                      while (pos < codigo.length() && (isNumeric(codigo.at(pos)) || codigo.at(pos) == '.' || codigo.at(pos) == '-' || codigo.at(pos) == '+')) {
                                          letra = codigo.at(pos++);
                                          x.append(letra);
                                      }
                                      break;
                                  case 'Y':
                                      if (!isNumeric(codigo.at(pos)) && codigo.at(pos) != '-' && codigo.at(pos) != '+') {
                                          comentario.append(letra);
                                          break;
                                      }
                                      y=QByteArray("");
                                      while (pos < codigo.length() && (isNumeric(codigo.at(pos)) || codigo.at(pos) == '.' || codigo.at(pos) == '-' || codigo.at(pos) == '+')) {
                                          letra = codigo.at(pos++);
                                          y.append(letra);
                                      }
                                        break;
                                  case 'Z':
                                      if (!isNumeric(codigo.at(pos)) && codigo.at(pos) != '-' && codigo.at(pos) != '+') {
                                          comentario.append(letra);
                                          break;
                                      }
                                      z=QByteArray("");
                                      while (pos < codigo.length() && (isNumeric(codigo.at(pos)) || codigo.at(pos) == '.' || codigo.at(pos) == '-' || codigo.at(pos) == '+')) {
                                          letra = codigo.at(pos++);
                                          z.append(letra);
                                      }
                                      break;
                                  default:
                                      if (letra != ' ') {
                                          do {
                                              comentario.append(letra);
                                              if (pos < codigo.length()) {
                                                  letra = codigo.at(pos++);
                                              }
                                          } while (pos < codigo.length() && letra != ' ');
                                          if (pos <= codigo.length()) {
                                              comentario.append(letra);
                                          }
                                      }
                                      break;
                              }
                          }
                          if (this->comentario.length() > 0 && !(this->comentario.at(0))=='/') {
                              if (x.length()>0 || y.length()>0 || z.length() ) {
                                  if (comentario.length()>0) {
                                      this->comentario.clear();
                                  }
                              }
                          }
                      }
                      
                      bool Coordenada2::isComentario() {
                          return !comentario.isEmpty();
                      }
                      
                      bool Coordenada2::isNull() {
                          if (!this->isX() && !this->isY() && !this->isZ()) {
                              return true;
                          } else {
                              return false;
                          }
                      }
                      
                      bool Coordenada2::isNumeric(const char &cadena) {
                          if ('0' <= cadena && cadena <= '9' )
                              return true;
                          else
                              return false;
                      }
                      

                      main.cpp

                      void leeArchivo(){
                      QFile archivo("c:\\coordenadas.txt");
                      int lineas = 0;
                      float maxX = -10000;
                      float maxY = -10000;
                      float minX = 10000;
                      float minY = 10000;
                      float maxZ = -10000;
                      float minZ = 10000;
                      bool hayX = false;
                      bool hayY = false;
                      Coordenada2 elementoAnterior();
                      if (archivo.open(QIODevice::ReadOnly | QIODevice::Text)){
                          QTextStream in(&archivo);
                          QElapsedTimer tiempo;
                          tiempo.start();
                          while (!in.atEnd()) {
                              lineas++;
                              Coordenada2 elemento(in.readLine().toLatin1());
                              if (maxX < elemento.getNumeroX()) {
                                  maxX = elemento.getNumeroX();
                              }
                              if (minX > elemento.getNumeroX()) {
                                  minX = elemento.getNumeroX();
                              }
                              if (maxY < elemento.getNumeroY()) {
                                  maxY = elemento.getNumeroY();
                              }
                              if (minY > elemento.getNumeroY()) {
                                  minY = elemento.getNumeroY();
                              }
                              if (maxZ < elemento.getNumeroZ()) {
                                  maxZ = elemento.getNumeroZ();
                              }
                              if (minZ > elemento.getNumeroZ() ) {
                                  minZ = elemento.getNumeroZ();
                              }
                              if (elemento.isX()) {
                                  hayX = true;
                              }
                              if (elemento.isY()) {
                                  hayY = true;
                              }
                          }
                          qDebug()<<"Tiempo :"<<tiempo.elapsed();
                          qDebug()<<maxX;
                          archivo.close();
                      }
                      }
                      
                      int main(int argc, char *argv[])
                      {
                      QApplication a(argc, argv);
                      
                      leeArchivo();
                      return 0;
                      }
                      

                      I've been testing to measure the creation times of Coordenada2 object for the first 50 lines of the file, and the result has been that Java was slower than QT creating each of the objects. But for the total of java linesis still much faster. I made a test by increasing the number of records and comparing the result in java and QT. The results are as follows:

                       java     QT  	lines
                          1	   0	    10
                          3	   0	   100
                          8	   1   	   300
                         13      2	  1000
                         18	   8	  3000
                         25	  27     10000
                         46	  84	 30000
                        104    295	100000
                        289	 936	300000
                        349	1199	371723
                      

                      As you can see java is much more lineal in time, every time we increase records, the time increases , however QT has some very good times to 10000 lines, but from there, the times are far higher than those of java. Any idea why his happens'

                      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 Extensions
                      • Unsolved