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.

Reply via email to