8000
Skip to content

Conversation

@Gatsik
Copy link
Contributor
@Gatsik Gatsik commented May 29, 2025

I needed to generate a bunch of plots and noticed that it was quite slow. This PR tries to reduce the number of overheads on initializing PlotWidget by implementing several optimizations:

  • Don't initialize ViewBoxMenu on PlotWidget init. Create them on mouse events (or when one wants ot access menu property explicitly) instead when needed -- many setupUi() calls required to create menu are expensive
  • Remove WidgetGroup from ViewBoxMenu -- they were unused there -- reduces expensive autoAdd() method recursions
  • Create helper methods to set only necessary AxisItem properties and avoid calling _updateLabel during initialization (setHtml is quite expensive!)
  • Don't set LabelItem text during initialization if text is empty (since setHtml is slow)
  • Remove slot connections by name from AxisItem and PlotItem UI templates (unused) (to avoid generating these calls, pass -a option to uic)
  • Replace some double dict lookups with try..except blocks

Here are my benchmarks with this script:

import time

from PyQt6.QtWidgets import QApplication

import pyqtgraph as pg


def main() -> int:
    app = QApplication([])
    start = time.perf_counter()
    for _ in range(20):
        pg.PlotWidget()
    end = time.perf_counter()
    print(end - start)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
  • before: 0.5176408999977866
  • after: 0.28181239999685204

And also cProfile results (before and after respectively):
profile_before
profile_after

obtained by running this script:

import cProfile

from PyQt6.QtWidgets import QApplication

import pyqtgraph as pg


def main() -> int:
    app = QApplication([])
    with cProfile.Profile() as pr:
        for _ in range(20):
            pg.PlotWidget()
    pr.dump_stats("profile.pstat")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

and converting results to svg with yelp-gprof2dot and graphviz

for label in self.axes:
try:
labels[label] = kwargs.pop(label)
except KeyError:

Check notice

Code scanning / CodeQL

Empty except Note

'except' clause does nothing but pass and there is no explanatory comment.
@Gatsik Gatsik force-pushed the plotwidget-init-speedup branch from 5522457 to d959deb Compare May 30, 2025 10:39
Multiple PlotWidget initialization is quite slow

* Don't initialize ViewBoxMenu on PlotWidget init
  Create them on mouse events instead when needed --
  many `setupUi()` calls are expensive
* Remove WidgetGroup from ViewBoxMenu -- they weren't used
  anywhere -- reduces expensive `autoAdd()` method recursions
* Create helper methods to set only necessary AxisItem properties
  and avoid calling `_updateLabel` during initialization
  (`setHtml` is quite expensive!)
* Don't set LabelItem text during initialization if text is empty
  (since `setHtml` is slow)
* Remove slot connections by name from Axis and PlotItem UI
  templates (unused) (to avoid generating these calls, pass `-a`
  option to `uic`)
* Replace some dict lookups with `try..except` blocks
and sort imports
in files affected by commit
20a9acd
@Gatsik Gatsik force-pushed the plotwidget-init-speedup branch from f3fcbd6 to 51fb081 Compare November 17, 2025 22:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0