It turns out ImageExporter is terribly optimized for speed. I assume the
authors designed it to be acceptable for one-shot screenshots, and never
tested it for exporting animations.
- Initializing image to background color:
- buf[:,:,0] = color.red()...etc. is slow.
- Solution? QImage.fill(color) is near-instant.
- GUI plots render to QPixmap (GPU/etc texture), and no copy is
performed?. Image plots are inherently slower since they require copying to
QImage (memory buffer).
- This is very slow with Format_ARGB32, but much faster with
Format_RGB32.
- Solution: I create QImage(w, h, Format_RGB32) without passing in
`bg` ndarray.
- Speed of various QImage formats:
- Format_RGB32 = 280fps or less
- Format_ARGB32 = 150fps or less
- Format_RGB888 = 110fps
- I have no need for an alpha channel when piping video frames to
ffmpeg, and I doubt many plots have transparent backgrounds.
- Initializes `self.bg` buffer and `self.png` QImage, and overwrites
with new objects during next screenshot (discards local QPainter too, but
it isn't a major slowdown)
- Not 100% sure if this causes slowdown. Changing QPainter(QPixmap())
and calling qpixmap.toImage() performs wasteful allocations? but isn't
noticeably slower than my final solution.
- Solution? Save and reuse QPainter and QImage (I renamed self.png to
qimage, and self.painter).
- Delete variable self.bg, since I let QImage allocate memory.
- self.setExportMode() is slow, but is called twice per screenshot
(once to enable, once to disable).
- Solution? Call it once during the first screenshot, and never turn
it back off.
- This is not an issue for me, since I never display the widgets
in a window.
- You could move enabling/disabling setExportMode to a `with`
statement, which Exporter callers are required to use.
- Called every frame: 180fps
- Called once: 250fps
- Not called: 200fps?
Source code for my modified ImageExporter:
https://gist.github.com/jimbo1qaz/24b0f74dfac8d48dc998bcf6a9451f96
On Wednesday, November 21, 2018 at 9:50:52 PM UTC-8, jimbo1qaz wrote:
> I'm developing an audio oscilloscope-type program, which outputs frames as
> raw bytes to ffmpeg and ffplay (which plays back video and audio together,
> synchronized). I can also tell ffmpeg to output to file instead.
>
> Originally I used matplotlib. I tried switching to pyqtgraph because I
> thought it would be faster.
>
> Unfortunately it ended up too slow for my use case.
>
> - Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz, turbo 2.70GHz
> - Windows 10 x64 (I can try Kubuntu 18.04 later)
> - Miniconda Python 3.6.6
> - pyqtgraph 0.11.0.dev0+g2e69b9c
>
> I adapted pyqtgraph's speed test to resemble my data more closely (hide
> all axises, no title, don't write fps to canvas):
>
> -
>
> https://gist.github.com/jimbo1qaz/472242d89a8fde421c39b4f86bf48b0e#file-pyqtgraph-speed-gui-py
> - output to GUI
> - 200-300fps
> -
>
> https://gist.github.com/jimbo1qaz/472242d89a8fde421c39b4f86bf48b0e#file-pyqtgraph-speed-image-py
> - output to QImage
> - starts at 766.36 fps, declines to 40-80fps (randomly toggles
> every few seconds, may possibly depend on window focus)
>
> In my own app rendering tests, I usually get 50-120fps, depending on data
> and number of plots. In any case, this is far worse than matplotlib with
> axis drawing disabled (118-158fps).
>
> In either case, stopping in PyCharm (which sends Ctrl+C) results in
> "Process finished with exit code -1" instead of a stacktrace, which
> prevents me from taking a cProfile snapshot of my above speed demo.
>
> I attached 2 cProfile logs. I closed the GUI after an approximate amount
> of time, and terminated the QImage code using "for i in range(600)".
>
--
You received this message because you are subscribed to the Google Groups
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/pyqtgraph/f8aca7b9-f044-485c-8e5c-fe0aab3ab5fb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.