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