Feature Request: Expose QPainter methods that accept pointers

Phil Thompson phil at riverbankcomputing.com
Sat May 28 09:18:04 BST 2022


On 28/05/2022 06:39, Ognyan Moore wrote:
> Hi Phil,
> 
> We started doing some benchmarking using the following script:
> 
> from PyQt6 import QtCore, QtGui
> import PyQt6.sip as sip
> import numpy as np
> 
> import itertools
> from time import perf_counter
> 
> class LineSegments:
>     def __init__(self, use_sip_array):
>         self.use_sip_array = hasattr(sip, 'array') and use_sip_array
>         self.alloc(0)
> 
>     def alloc(self, size):
>         if self.use_sip_array:
>             self.objs = sip.array(QtCore.QLineF, size)
>             vp = sip.voidptr(self.objs, len(self.objs)*4*8)
>             self.arr = np.frombuffer(vp, dtype=np.float64).reshape((-1, 
> 4))
>         else:
>             self.arr = np.empty((size, 4), dtype=np.float64)
>             self.objs = list(map(sip.wrapinstance,
>                 itertools.count(self.arr.ctypes.data, 
> self.arr.strides[0]),
>                 itertools.repeat(QtCore.QLineF, self.arr.shape[0])))
> 
>     def get(self, size):
>         if size != self.arr.shape[0]:
>             self.alloc(size)
>         return self.objs, self.arr
> 
> def run(size, use_sip_array):
>     qimg = QtGui.QImage(640, 480, QtGui.QImage.Format.Format_RGB32)
>     qimg.fill(QtCore.Qt.GlobalColor.transparent)
>     segments = LineSegments(use_sip_array)
>     objs, arr = segments.get(size)
> 
>     arr[:, 0] = 0
>     arr[:, 1] = 0
>     arr[:, 2] = qimg.width()
>     arr[:, 3] = qimg.height()
> 
>     painter = QtGui.QPainter(qimg)
>     painter.setPen(QtCore.Qt.GlobalColor.cyan)
> 
>     draw_t0 = perf_counter()
>     painter.drawLines(objs)
>     draw_t1 = perf_counter()
> 
>     painter.end()
>     return draw_t1 - draw_t0
> 
> size = int(1e6)
> for use_sip_array in [True, False]:
>     dt = run(size, use_sip_array)
>     print(f'{use_sip_array=} {dt:.3f}')
> 
> 
> Here we noticed that using sip.array was slightly faster than not on 
> macOS,
> but on Windows it was slightly slower.  Then when we changed the 
> endpoint
> of the line to (10, 10) instead of the width and height of the QImage 
> as
> such:
> 
> arr[:, 2] = 10
> arr[:, 3] = 10
> 
> We started seeing significantly higher penalties for using sip.array
> 
> On macOS:
> 
> use_sip_array=True 0.513
> use_sip_array=False 0.171
> 
> 
> On Windows:
> 
> use_sip_array=True 0.351
> use_sip_array=False 0.218
> 
> 
> Also for sanity sake, the output of pip list:
> 
> Package    Version             Editable project location
> ---------- ------------------- ------------------------------
> numpy      1.22.4
> pip        22.1.1
> PyQt6      6.3.1.dev2205201737
> PyQt6-Qt6  6.3.0
> PyQt6-sip  13.4.0
> pyqtgraph  0.12.4.dev0         /Users/ogi/Developer/pyqtgraph
> setuptools 58.1.0
> wheel      0.37.1
> 
> Let me know if there is another use case I should test.

That's what I would expect with that use case. You are creating the 
array each time you want to do a draw so there is no benefit. The 
benefit is when you create the array once and draw many times. In a 
previous email you said that approach was usable.

Phil


More information about the PyQt mailing list