ncssar / radiolog

SAR radio log program
Other
13 stars 3 forks source link

lag at first keypress to open new entry, only noticeable with team count >30 or so #671

Closed caver456 closed 9 months ago

caver456 commented 11 months ago

Noticed during #391, but confirmed that the lag was there in an earlier version (3.7.0):

caver456 commented 9 months ago

confirmed the same behavior exists after fi of #370. Lag is about 1 second at 30 teams. Lag still exists after load of 50 teams within same session after 30 teams were created by hand, but not after restart and load.

caver456 commented 9 months ago

There's not much code between those two lines:

    def openNewEntry(self,key=None,callsign=None,formattedLocString=None,fleet=None,dev=None,origLocString=None,amendFlag=False,amendRow=None,isMostRecentForCallsign=False):
        rprint("openNewEntry called:key="+str(key)+" callsign="+str(callsign)+" formattedLocString="+str(formattedLocString)+" fleet="+str(fleet)+" dev="+str(dev)+" origLocString="+str(origLocString)+" amendFlag="+str(amendFlag)+" amendRow="+str(amendRow)+" isMostRecentForCallsign="+str(isMostRecentForCallsign))
        self.clearSelectionAllTables() # in case copy or context menu was in process
        if clueDialog.openDialogCount==0:
            self.newEntryWindow.setWindowFlags(Qt.WindowTitleHint|Qt.WindowStaysOnTopHint) # enable always on top
        else:
            self.newEntryWindow.setWindowFlags(Qt.WindowTitleHint)
        sec=time.time() # epoch seconds, for sorting purposes; not displayed
        self.newEntryWidget=newEntryWidget(self,sec,formattedLocString,fleet,dev,origLocString,amendFlag,amendRow,isMostRecentForCallsign)

...

class newEntryWidget(QWidget,Ui_newEntryWidget):
    instances=[]
##  newEntryDialogPositionList=[]
##  newEntryDialogUsedPositionList=[]
##  for n in range(50):
##      newEntryDialogPositionList.append([newEntryDialog_x0+n*newEntryDialog_dx,newEntryDialog_y0+n*newEntryDialog_dy])
##      newEntryDialogUsedPositionList.append(False)
##  def __init__(self,parent,position,sec,formattedLocString='',fleet='',dev='',origLocString='',amendFlag=False,amendRow=None):
    def __init__(self,parent,sec=0,formattedLocString='',fleet='',dev='',origLocString='',amendFlag=False,amendRow=None,isMostRecentForCallsign=False):
        QDialog.__init__(self)

        self.ui=Ui_newEntryWidget()

        rprint('newEntryWidget __init__ called: formattedLocString='+str(formattedLocString)+' fleet='+str(fleet)+' dev='+str(dev)+' origLocString='+str(origLocString)+' amendFlag='+str(amendFlag)+' amendRow='+str(amendRow)+' isMostRecentForCallsign='+str(isMostRecentForCallsign))

...

the only loop is inside clearSelectionAllTables - try reducing this loop:

    def clearSelectionAllTables(self):
        self.ui.tableView.setCurrentIndex(QModelIndex())
        self.ui.tableView.clearFocus() # to get rid of dotted focus box around cell 0,0
        for teamTable in self.ui.tableViewList:
            if not isinstance(teamTable,str): # 'dummy' is the default initial entry
                teamTable.setCurrentIndex(QModelIndex())
                teamTable.clearFocus()
caver456 commented 9 months ago

but - cProfile shows not much time is actually spent in clearSelectionAllTables, and, commenting out that call from openNewEntry doesn't really change the lag noticably. Keep looking...

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        2    0.002    0.001   54.798   27.399 radiolog.py:1(<module>)
    382/1    0.002    0.000   54.770   54.770 {built-in method builtins.exec}
        1    0.017    0.017   54.000   54.000 radiolog.py:9426(main)
       33    0.002    0.000    5.372    0.163 radiolog.py:3797(keyPressEvent)
       30    0.003    0.000    5.354    0.178 radiolog.py:4425(openNewEntry)
       73    3.831    0.052    4.127    0.057 {built-in method setWindowFlags}
        5    3.920    0.784    4.037    0.807 {built-in method exec_}
        1    0.045    0.045    2.574    2.574 radiolog.py:3885(closeEvent)
        1    0.002    0.002    1.907    1.907 radiolog.py:724(__init__)
       31    0.000    0.000    1.439    0.046 radiolog.py:6998(keyPressEvent)

...
...

       62    0.004    0.000    0.016    0.000 radiolog.py:1325(clearSelectionAllTables)
caver456 commented 9 months ago

Commenting out these lines (but leaving the call to clearSelectionAllTables in play) gets rid of the lag - zero noticeable lag even after adding 50 teams by hand:

    if clueDialog.openDialogCount==0:
        self.newEntryWindow.setWindowFlags(Qt.WindowTitleHint|Qt.WindowStaysOnTopHint) # enable always on top
    else:
        self.newEntryWindow.setWindowFlags(Qt.WindowTitleHint)

Interesting that it's not being called in a loop - so the loop must be internal to setWindowFlags or something at the OS level...?

Also, do we really need to set the window flags on the new entry window every time openNewEntry is called? newEntryWindow is created during startup, and is only hidden or shown as needed - but it's the same window. Seems like we should be able to set the flags once at startup, and only adjust if there's a pending clue dialog or such, which is what it looks like this clause is meant to do.

In other words: exactly what would be sacrificed by commenting out these lines? Need to test stays-on-top behavior, with and without a pending clue dialog, with and without these lines.

caver456 commented 9 months ago

Decided to take the minimally invasive / don't-rock-the-boat route: keep the same functionality but reduce the number of calls to setWindowFlags, by storing the flags state in a parallel variable (self.NEWFlags) and only calling setWindowFlags if there has been a change to the value.

Confirmed this works as expected, and there is no noticeable lag after 30 teams, then triggering the change by adding another team when there is a pending clue dialog, then adding 30 more teams.