Notes on Humbug development including extending the mindspace view with expandable sections and profiling performance bottlenecks in the file view.
Extending the mindspace view
Continued working on the mindspace view.
Modified the new view sections so they have expanders that allow their respective trees to be expanded or collapsed. By making this change I was able to make the section heading act like the root directory and thus support a context menu. This in turn meant the top-level folder could be removed from each section, giving back one row per section, but also one entire level of horizontal indentation. This reduces the screen real estate for the trees and makes them easier to use.
Profiling a performance bottleneck
I'd planned to remove the "sort by creation date" feature from the file view anyway, but realized this was suddenly taking a huge amount of time to handle initial expansion of parts of the files tree.
The following code snippet was useful as it triggered 2 seconds of profiling, started by the tree expand signal:
import cProfile
profiler = cProfile.Profile()
def _stop_profiling(self) -> None:
"""Stop profiling the tree view."""
self.profiler.disable()
self.profiler.print_stats(sort="time")
def _tree_expanded(self, index: QModelIndex) -> None:
"""Handle tree expansion events."""
print("Tree expanded:", index.data())
timer = QTimer(self)
timer.setSingleShot(True)
timer.timeout.connect(self._stop_profiling)
timer.start(2000)
self.profiler.enable()
This provided a smoking gun around JSON parsing:
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
6086 2.327 0.000 2.327 0.000 decoder.py:351(raw_decode)
6086 0.140 0.000 0.267 0.000 {method 'read' of '_io.TextIOWrapper' objects}
6086 0.126 0.000 0.126 0.000 {built-in method _codecs.utf_8_decode}
6086 0.047 0.000 0.049 0.000 {built-in method _io.open}
6086 0.047 0.000 2.744 0.000 mindspace_files_model.py:157(_get_file_creation_time)
51/15 0.019 0.000 2.791 0.186 {function HumbugApplication.notify at 0x108d94cc0}
6086 0.009 0.000 2.681 0.000 mindspace_files_model.py:112(_get_conversation_timestamp)
3158 0.009 0.000 2.765 0.001 mindspace_files_model.py:210(lessThan)
6086 0.006 0.000 0.006 0.000 {method '__exit__' of '_io._IOBase' objects}
12402 0.005 0.000 0.010 0.000 mindspace_files_model.py:77(_is_in_conversations_hierarchy)
6086 0.005 0.000 2.336 0.000 decoder.py:340(decode)
6480 0.005 0.000 0.005 0.000 {method 'filePath' of 'PySide6.QtWidgets.QFileSystemModel' objects}
6086 0.004 0.000 2.611 0.000 __init__.py:274(load)
24804 0.004 0.000 0.004 0.000 {built-in method posix._path_normpath}
45 0.004 0.000 0.004 0.000 {function MindspaceFilesDelegate.paint at 0x108cca160}
6086 0.003 0.000 0.016 0.000 mindspace_files_model.py:95(_is_conversation_file)
6086 0.003 0.000 2.340 0.000 __init__.py:299(loads)
6152 0.003 0.000 0.007 0.000 <frozen posixpath>:117(splitext)
6086 0.003 0.000 0.003 0.000 {method 'timestamp' of 'datetime.datetime' objects}
6152 0.002 0.000 0.004 0.000 <frozen genericpath>:157(_splitext)
30740 0.002 0.000 0.002 0.000 {built-in method builtins.isinstance}
12172 0.002 0.000 0.002 0.000 {method 'match' of 're.Pattern' objects}
6086 0.002 0.000 0.127 0.000 <frozen codecs>:322(decode)
Implemented a simple caching solution for the conversations view and now applications load times have dramatically reduced! Looks like they're now several hundred ms faster.