PyQt5 graph view "lazy loading" seems broken with graphopt
*Created originally on Bitbucket by [lothiraldan (Boris FELD)](https://bitbucket.org/%7B9265a420-a059-4969-b511-cb4f5ecdba07%7D/)* I am debugging a performance issue on a pretty big repository (~525000 revisions). The repository is also quite branchy (+20000 heads). All the tests were made on a Mac Mini Sierra (10.12.6). Opening the repository with thg 4.5 Qt4 (https://bitbucket.org/tortoisehg/files/downloads/TortoiseHg-4.5.0-mac-x64-qt4.dmg) takes between 6 to 8 seconds to load when I'm on tip and 12 to 14 seconds when I'm on revision 500000. Opening the repository with thg 4.5 Qt5 (https://bitbucket.org/tortoisehg/files/downloads/TortoiseHg-4.5.0-mac-x64-qt4.dmg) takes forever when I'm on tip or not (more than 1 hour). In both cases, the `graphopt` option has been set. I've tried to diagnosticate it with the `showstack` extension and it seems that https://bitbucket.org/tortoisehg/thg/src/d0648f267bec60191f6fe323a69b8cfb404a7189/tortoisehg/hgqt/repomodel.py?at=default&fileviewer=file-view-default#repomodel.py-565 is called for each row in the Qt5 version but not in the Qt4 version. I tried adding a traceback, but the traceback are not very helpful. I got two different tracebacks: ``` File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 249, in _runcatch File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 340, in runcommand File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 391, in _runcommand File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 345, in checkargs File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 339, in <lambda> File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/qtapp.py", line 471, in __call__ File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repowidget.py", line 261, in _initView File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repowidget.py", line 860, in _updateRepoViewForModel File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repomodel.py", line 667, in defaultIndex File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repomodel.py", line 586, in flags ``` and ``` File ".../TortoiseHg45qt4.app/Contents/Resources/__boot__.py", line 82, in _run File ".../TortoiseHg45qt4.app/Contents/Resources/thg.py", line 116, in <module> File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 48, in dispatch File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 249, in _runcatch File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 340, in runcommand File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 391, in _runcommand File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 345, in checkargs File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 339, in <lambda> File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/qtapp.py", line 471, in __call__ File ".../TortoiseHg45qt4.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repomodel.py", line 586, in flags ``` Both tracebacks seems to be missing the frames in PyQt. I then tried to add a debug line: ``` diff --git a/tortoisehg/hgqt/repomodel.py b/tortoisehg/hgqt/repomodel.py --- a/tortoisehg/hgqt/repomodel.py +++ b/tortoisehg/hgqt/repomodel.py @@ -567,6 +567,7 @@ class HgRepoListModel(QAbstractTableMode if not index.isValid(): return flags row = index.row() + print("Flags", row) if row >= len(self.graph) and not self.repo.ui.debugflag: # TODO: should not happen; internal data went wrong (issue #754) return Qt.NoItemFlags ``` Running with this debug line on the Qt4 version output these lines: ``` ('Flags', 25864) * 2 # The first line is repeated 2 times ('Flags', 25855) * 17 # This line is repeated 17 times ('Flags', 25856) * 17 ('Flags', 25857) * 17 ... QPainter::begin: Paint device returned engine == 0, type: 2 QPainter::setCompositionMode: Painter not active ('Flags', 25855) * 3 ('Flags', 25856) * 3 ('Flags', 25857) * 3 ('Flags', 25858) * 3 ... ``` It generates ~300 lines of output but ends-up loading. Running the Qt5 version is different. The traceback are similar (lines are different because I tried adding more or less lines in one version): ``` File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 249, in _runcatch File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 340, in runcommand File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 391, in _runcommand File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 345, in checkargs File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 339, in <lambda> File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/qtapp.py", line 471, in __call__ File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repowidget.py", line 261, in _initView File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repowidget.py", line 860, in _updateRepoViewForModel File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repomodel.py", line 663, in defaultIndex File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repomodel.py", line 582, in flags ``` and another one that is different: ``` File ".../TortoiseHg45qt5.app/Contents/Resources/__boot__.py", line 82, in _run File ".../TortoiseHg45qt5.app/Contents/Resources/thg.py", line 116, in <module> File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 48, in dispatch File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 249, in _runcatch File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 340, in runcommand File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 391, in _runcommand File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 345, in checkargs File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/run.py", line 339, in <lambda> File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/qtapp.py", line 471, in __call__ File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repowidget.py", line 261, in _initView File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repowidget.py", line 862, in _updateRepoViewForModel File ".../TortoiseHg45qt5.app/Contents/Resources/lib/python2.7/tortoisehg/hgqt/repomodel.py", line 582, in flags ``` The output seems to show that it's trying to render every rows at launch: ``` ('Flags', 0) * 2 # The first line is repeated 2 times ('Flags', 1) * 2 # This line is repeated 2 times ('Flags', 2) * 2 ('Flags', 3) * 2 ... ``` I tried diffing the Qt4 and Qt5 versions but nothing seems to explain this difference, could it be because of PyQt4 vs PyQt5?
issue