QProgressBar causing bad performance in QT5?



  • I'm developping a program which parses a file (365000 lines) in which I try to match some keywords after reading each line. This computation along with the update of my QProgressBar are made in another thread using QThread. Everything works fine except for the performance especially when I update the QProgressBar. I use a timer for the parsing and the result is just STUNNING. When I emit a signal to update the QProgressBar the program takes around 45 seconds but when I do not emit the signal for the QProgressBar update then the program takes around 0.40 sec =/

    from PyQt5 import QtCore, QtWidgets, QtGui
    import sys
    import time
    
    liste = ["failed", "exception"]
    
    class ParseFileAsync(QtCore.QThread):
    
        match = QtCore.pyqtSignal(str)
        PBupdate = QtCore.pyqtSignal(int)
        PBMax = QtCore.pyqtSignal(int)
    
        def run(self):        
            cpt = 0
            with open("shutdown_issue_1009.log", "r") as fichier:
                fileLines = fichier.readlines()  
                lineNumber = len(fileLines)    
                self.PBMax.emit(lineNumber)
            
                t0 = time.time()
                for line in fileLines:
                    cpt+=1
                    self.PBupdate.emit(cpt)   
                    for element in liste:
                        if element in line:
                            self.match.emit(line)
            
            finalTime = time.time() - t0
            print("over :", finalTime)
    
        class Ui_MainWindow(QtWidgets.QMainWindow):
    
            def __init__(self):
                super().__init__()       
                self.setupUi(self)
                self.thread = ParseFileAsync()
        
                self.thread.match.connect(self.printError)
                self.thread.PBupdate.connect(self.updateProgressBar)
                self.thread.PBMax.connect(self.setMaximumProgressBar)
        
                self.pushButton_GO.clicked.connect(self.startThread)
    
            def printError(self, line):
                self.textEdit.append(line)
    
            def updateProgressBar(self, value):
                self.progressBar.setValue(value)
        
            def setMaximumProgressBar(self, value):
                self.progressBar.setMaximum(value)
        
            def startThread(self):
                self.thread.start()
    

    Console output:

    over : 44.49321101765038  //QProgressBar updated
    over : 0.3695987798147516 //QProgressBar not updated (#self.PBupdate.emit(cpt))
    

    Am I missing something or is that expected ?


  • Qt Champions 2016

    Hi
    I dont know python, but if in a c++ application
    i would try the same
    with no slot connected to see if it was sending the signal
    very fast that was the issue.
    So try to emit but dont respond to it.
    If still fast i would look at the slot.
    Using Progressbar in c++, i didn't notice such huge difference and painting
    the bar etc should not be so expensive.

    But if it takes 0.3 sec. do u really need a progress bar anyway?



  • I did the test and appearantly it's the painting which is very expensive... with no slot connected, the program takes 1,5 seconds to complete the task. There is a very similar issue reported at https://bugreports.qt.io/browse/QTBUG-49655.

    But generally ProgressBars are consuming especially when we update it that often (>365000 times) while there is no significant change at each iteration. So I simply update the QProgressBar less often and the results are good (~1s) and the progression still smooth. PSB :

    class ParseFileAsync(QtCore.QThread):
        
        match = QtCore.pyqtSignal(str)
        PBupdate = QtCore.pyqtSignal(int)
        PBMax = QtCore.pyqtSignal(int)
    
        def run(self):        
            with open("test_long.log", "r") as fichier:
                fileLines = fichier.readlines()  
                self.lineNumber = len(fileLines)
                self.PBMax.emit(self.lineNumber)
    
                if (self.lineNumber < 30):
                    self.parseFile(fileLines, False)
                else:
                    self.parseFile(fileLines, True)
        
        def parseFile(self, fileLines, isBig):                
                cpt = 0
                        
                if(isBig):
                    for line in fileLines:
                        cpt+=1             
                        if(cpt % (int(self.lineNumber/30)) == 0):
                            self.PBupdate.emit(cpt)        
                        for element in liste:
                            if element in line:
                                self.match.emit(line)
                    
                    self.PBupdate.emit(self.lineNumber) #To avoid QProgressBar stopping at 99%
                else:         
                    for line in fileLines:
                        cpt+=1                
                        self.PBupdate.emit(cpt)                                  
                        for element in liste:
                            if element in line:
                                self.match.emit(line)
    


Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.