June 16, 2011

maxoreli maxoreli
Lab Rat
46 posts

Problem for slow operations in Qt program

Page  
1

hi,I ‘m working on a program and i have some problems about performance of my projet. By example, during running of my program, if i want show a widget(to screen) ,it take long time before which widget become visible,or ,i make send a result to user that’s make long time too. I want ,during this long time , show a dialog which is used to give the user an indication of how long an operation is going to take, and to demonstrate that the application has not frozen Thanks for advanc

25 replies

June 16, 2011

mlong mlong
Mad Scientist
1517 posts

Are you doing something time consuming in a single threaded application? If so, you may want to consider moving whatever’s taking a long time into it’s own thread.

 Signature 

Senior Software Engineer
AccuWeather Enterprise Solutions
/* My views and opinions do not necessarily reflect those of my employer.  Void where prohibited. */

June 16, 2011

ludde ludde
Ant Farmer
325 posts

Did you have a look at QProgressDialog [doc.qt.nokia.com]?

June 16, 2011

Andre Andre
Area 51 Engineer
6031 posts

If a dialog is taking long to show, you are probably doing too much work in the constructor of the dialog. Instead, try to postphone doing that work untill a little bit later when you have returned to the eventloop again. To keep your UI responsive, it is important not to execute too time consuming operations in the main thread. Instead, either move the operation to a thread of its own, or devide it up into smaller blocks and return to the eventloop regulary. Try to avoid using processEvents() for that though. Instead, considder using a 0-timer to trigger the processing of the next block using a slot, and continue doing that untill your processing queue is empty or you have completed your processing pipeline.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

June 22, 2011

maxoreli maxoreli
Lab Rat
46 posts

I’m trying use Qthread ,but running of my program dont start.
this is class of my object

  1. #include "formdp0j_poj.h"
  2. #include "forms0ixmij_x_q0ij.h"
  3. #include "forms1ixmij_x_q1ij.h"
  4. #include "forms2ixmij_x_q2ij.h"
  5. #include"mythread.h"
  6.  
  7. FormdP0j_Poj::FormdP0j_Poj(QWidget *parent) :
  8.     QWidget(parent)
  9. {
  10.     setupUi(this);
  11.     table=new QTableWidget;
  12.     table->setRowCount(5);
  13.     table->setColumnCount(40);
  14.     setupContents();
  15.    calculate();
  16. }
  17.  
  18. void FormdP0j_Poj::changeEvent(QEvent *e)
  19. {
  20.     QWidget::changeEvent(e);
  21.     switch (e->type()) {
  22.     case QEvent::LanguageChange:
  23.         retranslateUi(this);
  24.         break;
  25.     default:
  26.         break;
  27.     }
  28. }
  29.  
  30. void FormdP0j_Poj::setupContents()
  31. {
  32.  
  33. //in the constructor's widget,i m doing long operations too
  34.     FormS0ixmij_x_q0ij *matrixS0ixmij_x_q0ij=new  FormS0ixmij_x_q0ij;
  35.  
  36.    FormS1ixmij_x_q1ij *matrixS1ixmij_x_q1ij=new FormS1ixmij_x_q1ij;
  37.  
  38.    FormS2ixmij_x_q2ij *matrixS2ixmij_x_q2ij=new FormS2ixmij_x_q2ij;
  39.  
  40.  
  41.  
  42.     tempS0ixmij_x_q0ij= matrixS0ixmij_x_q0ij->getTable();
  43.    tempS1ixmij_x_q1ij= matrixS1ixmij_x_q1ij->getTable();
  44.    tempS2ixmij_x_q2ij= matrixS2ixmij_x_q2ij->getTable();
  45.  
  46.     QVariant variant;
  47.     QTableWidgetItem * curItem=new QTableWidgetItem;
  48.  
  49.  
  50.     if(  (tempS0ixmij_x_q0ij!=0)   &&  (tempS1ixmij_x_q1ij !=0 ) &&  (tempS2ixmij_x_q2ij !=0) ){
  51.  
  52.  
  53.         //copie de l'entete
  54.         int c=1;
  55.         table->setItem(1,0,new QTableWidgetItem(QString("dP0j/P0j")));
  56.         table->setItem(2,0,new QTableWidgetItem(QString("dP1j/P1j")));
  57.         table->setItem(3,0,new QTableWidgetItem(QString("dP2j/P2j")));
  58.         //table->setItem(4,0,new QTableWidgetItem(QString("q")));
  59.  
  60.         for(int j=1; j < tempS0ixmij_x_q0ij->columnCount()  ;j=j+1)
  61.         {
  62.             curItem=new QTableWidgetItem;
  63.             variant= tempS0ixmij_x_q0ij->item(0,j)->data(0);
  64.             curItem->setData(0,variant);
  65.             table->setItem(0,c,curItem);
  66.             c=c+1;
  67.         }
  68.  
  69.  
  70.         //1ere ligne
  71.         double coef,a,b;
  72.         int RCount=tempS0ixmij_x_q0ij->rowCount();
  73.         int CCount=tempS0ixmij_x_q0ij->columnCount();
  74.          QTableWidgetItem * curItem=new QTableWidgetItem;
  75.  
  76.         for( int j =1; j <  CCount ;j=j+1
  77.         {
  78.             c=1; coef=0.;
  79.             for( int i=1 ; j < RCount  ;i=i+1 )
  80.             {
  81.                if ((tempS0ixmij_x_q0ij->item(i,j) !=0)){
  82.  
  83.                    a= (tempS0ixmij_x_q0ij->item(i,j)->data(0).toDouble());
  84.                    coef= coef + a;
  85.                 }
  86.  
  87.             }
  88.            curItem=new QTableWidgetItem;
  89.             curItem->setData(0,coef);
  90.            table->setItem(1,c,curItem);
  91.             c=c+1;
  92.             QCoreApplication::processEvents();
  93.         }
  94.  
  95.  
  96.         table->resizeColumnsToContents();
  97.         table->resizeRowsToContents();
  98.         horizontalLayout->addWidget(table);
  99.     }
  100.  
  101.  
  102. }
  103.  
  104. void FormdP0j_Poj::calculate()
  105. {
  106.    //calcul des coefficients
  107.  
  108.  
  109.     //2 ligne
  110.     for( int j =1; j < tempS1ixmij_x_q1ij->columnCount() ;j=j+1 )
  111.     {
  112.         c=1; coef=0.;
  113.         for( int i=1 ; j < tempS1ixmij_x_q1ij->rowCount()  ;i=i+1 )
  114.         {
  115.             if ((tempS1ixmij_x_q1ij->item(i,j) !=0)){
  116.  
  117.                 a=tempS1ixmij_x_q1ij->item(i,j)->data(0).toDouble();
  118.                 coef= coef + a;
  119.             }
  120.  
  121.         }
  122.         curItem=new QTableWidgetItem;
  123.         curItem->setData(0,coef);
  124.         table->setItem(2,c,curItem);
  125.         c=c+1;
  126.        // QCoreApplication::processEvents();
  127.     }
  128.  
  129.  
  130.     //3 ligne
  131.     for( int j =1; j < tempS1ixmij_x_q1ij->columnCount() ;j=j+1 )
  132.     {
  133.         c=1; coef=0.;
  134.         for( int i=1 ; j < tempS1ixmij_x_q1ij->rowCount()  ;i=i+1 )
  135.         {
  136.             if ((tempS2ixmij_x_q2ij->item(i,j) !=0)){
  137.  
  138.                 a=tempS2ixmij_x_q2ij->item(i,j)->data(0).toDouble();
  139.                 coef= coef + a;
  140.             }
  141.  
  142.         }
  143.         curItem=new QTableWidgetItem;
  144.         curItem->setData(0,coef);
  145.         table->setItem(3,c,curItem);
  146.         c=c+1;
  147.  
  148.     }
  149. }

and after i ‘m calling my widget in a mainwindow’s slot

  1. void MainWindow::on_actionDP0j_Poj_dP2j_P2j_triggered()
  2. {
  3.  
  4.     FormdP0j_Poj *w=new  FormdP0j_Poj;
  5.     int indexNouvelOnglet = onglets->addTab(createPageOnglet(w), tr("Matrix(dP0j/P0j à dP2j/P2j"));
  6.     onglets->setCurrentIndex(indexNouvelOnglet);
  7. }

and the main
  1. #include "mainwindow.h"
  2. #include<QPushButton>
  3.  
  4.  
  5. int main(int argc, char *argv[])
  6. {
  7.     QApplication a(argc, argv);
  8.  
  9.       MainWindow *mainw=new MainWindow;
  10.       mainw->show();
  11.  
  12.  
  13.     return a.exec();
  14. }

so ,when i run, program dont respond.
Thanks for advance

June 24, 2011

mlong mlong
Mad Scientist
1517 posts

Where are you using a threads? It’s hard to tell from the code you posted.

Edit: Also, remember, GUI elements (widgets) cannot be in any other thread except the main thread.

 Signature 

Senior Software Engineer
AccuWeather Enterprise Solutions
/* My views and opinions do not necessarily reflect those of my employer.  Void where prohibited. */

June 25, 2011

marcoB marcoB
Ant Farmer
167 posts

I never tried and don’t know it is the right way to go on, but a shortcut to this problem could be put this

  1. QTimer::singleShot(100, this, setupContents());

in your constructor. You will need to define setupContents() as a slots and then call calculate(); at the end of setupContents() function.

June 25, 2011

maxoreli maxoreli
Lab Rat
46 posts

Ok,i know, i dont put in this code, but how do I use QThread, for speed up my program .
Please explain me or give an sample of code.
Thanks for advance.

mlong wrote:
Where are you using a threads? It’s hard to tell from the code you posted.

Edit: Also, remember, GUI elements (widgets) cannot be in any other thread except the main thread.

June 25, 2011

TobbY TobbY
Lab Rat
208 posts

is using threads speed up program????

 Signature 

Gorilla..

June 25, 2011

maxoreli maxoreli
Lab Rat
46 posts

TobbY wrote:
is using threads speed up program????

Please help me,I have already documentationon Qthread, i dont know how to apply that, please show me how do this and give a sample of code.
Thanks for advance.

June 25, 2011

maxoreli maxoreli
Lab Rat
46 posts

marcoB wrote:
I never tried and don’t know it is the right way to go on, but a shortcut to this problem could be put this

  1. QTimer::singleShot(100, this, setupContents());

in your constructor. You will need to define setupContents() as a slots and then call calculate(); at the end of setupContents() function.

marcoB wrote:
I never tried and don’t know it is the right way to go on, but a shortcut to this problem could be put this

  1. QTimer::singleShot(100, this, setupContents());

in your constructor. You will need to define setupContents() as a slots and then call calculate(); at the end of setupContents() function.

I’m trying that,but i have same problems

June 25, 2011

Santosh Reddy Santosh Reddy
Lab Rat
42 posts

maxoreli wrote:

marcoB wrote:
I never tried and don’t know it is the right way to go on, but a shortcut to this problem could be put this

  1. QTimer::singleShot(100, this, setupContents());

in your constructor. You will need to define setupContents() as a slots and then call calculate(); at the end of setupContents() function.

marcoB wrote:
I never tried and don’t know it is the right way to go on, but a shortcut to this problem could be put this

  1. QTimer::singleShot(100, this, setupContents());

in your constructor. You will need to define setupContents() as a slots and then call calculate(); at the end of setupContents() function.

I’m trying that,but i have same problems

What is the problem ?

You can add QProgressBar, to indicate the status of setupContents()

 Signature 

SS

June 26, 2011

marcoB marcoB
Ant Farmer
167 posts

After singleShot call, your GUI should respond to user, even if I noticed now you put some

  1. QCoreApplication::processEvents();

in your loops and that could be enough to achieve what you are looking for.
Has Santosh sayd, try to put a progressBar in your form, it should works

June 26, 2011

Andre Andre
Area 51 Engineer
6031 posts

I find that progressEvents, especially the call without any arguments, is a road to very hard to debug issues. I try to avoid it.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

June 26, 2011

maxoreli maxoreli
Lab Rat
46 posts
Hello,Andre please I have difficulty to apply what you saw in your first reply. Please ,read my code and give an sample of code and how do I do it(speed up my program) Thanks for advance.
Andre wrote:
I find that progressEvents, especially the call without any arguments, is a road to very hard to debug issues. I try to avoid it.

June 26, 2011

Andre Andre
Area 51 Engineer
6031 posts

In the code you posted, you are not using threads; at least not where we can see them.

Your main issue is, that you are starting your intensive code from the constructor of your form. As you have been told before, you should not do that. Instead, you could re-write your constructor to something like this:

  1. FormdP0j_Poj::FormdP0j_Poj(QWidget *parent) :
  2.     QWidget(parent)
  3. {
  4.     setupUi(this);
  5.     table=new QTableWidget;
  6.     table->setRowCount(5);
  7.     table->setColumnCount(40);
  8.     // trigger heavy work to be done in a little while
  9.     QTimer::singleShot(100, this, SLOT(startHeavyWork()));
  10. }
  11.  
  12. //this needs to be a slot in your declaration
  13. FormdP0j_Poj::startHeavyWork()
  14. {
  15.     setupContents();
  16.     calculate();
  17. }

That should at least get your form displayed properly, if not responding well yet.

I am guessing your calculate function may take quite a bit of time, right? Assuming that it is indeed this function that takes most time (and not the setupContents function), let’s continue our optimization:

So, the calculate function is a candidate to make run asynchronous. That is: it running should not block your GUI. One problem is, is that your current function will impact the GUI (it creates QTableWidgetItems), and is thus not suited to put in a thread. Doing things in your GUI from another thread is not allowed. Lucky for you, the calculate function is an easy candidate to chop into pieces that can be run one after another, and return to the main loop in between.

How you make the split in blocks exactly, depends on your problem. It might take some experimentation. I have no idea how big the data sets you are working with are, and how much time each iteration may take. My goal would be to make sure you return to the eventloop at least 24 times per second, but again: some experimentation would be needed.

Lets start by re-arranging your calculation a bit: you are looping over the exact same two data structures in both the blocks of your calculation. That is a waste of time. Instead, loop over them only one time, and perform both calculations in one go:

  1. //calculation, version 2
  2. void FormdP0j_Poj::calculate()
  3. {
  4.    //calcul des coefficients
  5.  
  6.    // you seem to be missing some variable declarations. Did you cut those out?
  7.  
  8.  
  9.     //2 ligne
  10.     for( int j =1; j < tempS1ixmij_x_q1ij->columnCount() ;j=j+1 )
  11.     {
  12.         c=1; coef=0.; //where are these declared?
  13.         for( int i=1 ; j < tempS1ixmij_x_q1ij->rowCount()  ;i=i+1 )
  14.         {
  15.             if ((tempS1ixmij_x_q1ij->item(i,j) !=0)){
  16.  
  17.                 a=tempS1ixmij_x_q1ij->item(i,j)->data(0).toDouble();
  18.                 coef= coef + a;
  19.             }
  20.  
  21.             if ((tempS2ixmij_x_q2ij->item(i,j) !=0)){
  22.  
  23.                 a2=tempS2ixmij_x_q2ij->item(i,j)->data(0).toDouble();
  24.                 coef2= coef2 + a2;
  25.             }
  26.  
  27.         }
  28.         curItem=new QTableWidgetItem;
  29.         curItem->setData(0,coef);
  30.         table->setItem(3,c,curItem);
  31.  
  32.         curItem2=new QTableWidgetItem;
  33.         curItem2->setData(0,coef2);
  34.         table->setItem(3,c,curItem2);
  35.         c=c+1;
  36.  
  37.     }
  38. }

Let us assume that each iteration of your outer loop takes roughly 10 to 40ms. That is, after each iteration, we would like to return to the event loop. This is how you could do that:

  1. //calculation, version 3
  2. void FormdP0j_Poj::calculate()
  3. {
  4.    //calcul des coefficients
  5.    m_working = true; // declared as bool class member
  6.    m_workCurrentIteration = 0; //declared as int class member
  7.    m_workIterationCount = tempS1ixmij_x_q1ij->columnCount(); //also an int member
  8.  
  9.    QTimer::singleShot(0, this, SLOT(doWorkIteration()));
  10. }
  11.  
  12. //declared as slot in the class declaration
  13. void FormdP0j_poj::doWorkIteration()
  14. {
  15.    // you seem to be missing some variable declarations. Did you cut those out?
  16.  
  17.     int j = m_workCurrentIteration;
  18.  
  19.         c=1; coef=0.; //where are these declared?
  20.         for( int i=1 ; j < tempS1ixmij_x_q1ij->rowCount()  ;i=i+1 )
  21.         {
  22.             if ((tempS1ixmij_x_q1ij->item(i,j) !=0)){
  23.  
  24.                 a=tempS1ixmij_x_q1ij->item(i,j)->data(0).toDouble();
  25.                 coef= coef + a;
  26.             }
  27.  
  28.             if ((tempS2ixmij_x_q2ij->item(i,j) !=0)){
  29.  
  30.                 a2=tempS2ixmij_x_q2ij->item(i,j)->data(0).toDouble();
  31.                 coef2= coef2 + a2;
  32.             }
  33.  
  34.         }
  35.         curItem=new QTableWidgetItem;
  36.         curItem->setData(0,coef);
  37.         table->setItem(3,c,curItem);
  38.  
  39.         curItem2=new QTableWidgetItem;
  40.         curItem2->setData(0,coef2);
  41.         table->setItem(3,c,curItem);
  42.         c=c+1;
  43.  
  44.     }
  45.  
  46.    //prepare for the next iteration
  47.    ++m_workCurrentIteration;
  48.    if (m_workCurrentIteration < m_workIterationCount) {
  49.       //this is the trick: we schedule another iteration to be calculated if we need to do more work
  50.       QTimer::singleShot(0, this, SLOT(doWorkIteration()));
  51.    } else {
  52.       m_working = false;
  53.       workDone();
  54.    }
  55. }
  56.  
  57. void FormdP0j_poj::workDone()
  58. {
  59.     // this method is called when all the iterations are done. You might want to update the GUI to reflect that the calculation is done.
  60. }

A method like this will make sure you return to your eventloop regulary, thus giving your GUI the chance to update. Note that it will not make it run faster. In fact, it will be slower. But it will keep your users more happy. Using a thread might make your code faster, as your code can potentially use more cores in a multi-core machine. However, if you want to use threads, you can not interweave creating QTableWidgetItems into the calculation code. Instead, you’d have to store the results elsewhere. If you want to go that route, I think using QtConcurrent would be a feasable way to go.

disclaimer: all code presented here has just been typed into the editor of the forum. It is not tested, and only intended as an example.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

Page  
1

  ‹‹ Best way to populate a QTableView or QTableWidget with Excel data (urgent)      Do you do Qt development for mobile? ››

You must log in to post a reply. Not a member yet? Register here!