From 6185675c937604decadbe4c47fd31a07c256fe2a Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 22 May 2024 12:19:13 +1000 Subject: [PATCH] Additional shortcut to QgsAttributes creation from Python Avoid constructing a bunch of default QVariant objects which we will just replace immediately --- python/PyQt6/core/auto_generated/qgsattributes.sip.in | 10 +++++++--- python/core/auto_generated/qgsattributes.sip.in | 10 +++++++--- src/core/qgsattributes.h | 10 +++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/python/PyQt6/core/auto_generated/qgsattributes.sip.in b/python/PyQt6/core/auto_generated/qgsattributes.sip.in index c6e42099a2b..e51f86b72d6 100644 --- a/python/PyQt6/core/auto_generated/qgsattributes.sip.in +++ b/python/PyQt6/core/auto_generated/qgsattributes.sip.in @@ -70,9 +70,12 @@ typedef QVector QgsAttributes; return 1; } - QgsAttributes *qv = new QgsAttributes; Py_ssize_t listSize = PyList_GET_SIZE( sipPy ); - qv->resize( listSize ); + // Initialize attributes to null. This has two motivations: + // 1. It speeds up the QVector construction, as otherwise we are creating n default QVariant objects (default QVariant constructor is not free!) + // 2. It lets us shortcut in the loop below when a Py_None is encountered in the list + const QVariant nullVariant( QVariant::Int ); + QgsAttributes *qv = new QgsAttributes( listSize, nullVariant ); QVariant *outData = qv->data(); for ( Py_ssize_t i = 0; i < listSize; ++i ) @@ -80,7 +83,8 @@ typedef QVector QgsAttributes; PyObject *obj = PyList_GET_ITEM( sipPy, i ); if ( obj == Py_None ) { - *outData++ = QVariant( QVariant::Int ); + // outData was already initialized to null values + *outData++; } else if ( PyBool_Check( obj ) ) { diff --git a/python/core/auto_generated/qgsattributes.sip.in b/python/core/auto_generated/qgsattributes.sip.in index f0a0c5e956c..181b3997b3e 100644 --- a/python/core/auto_generated/qgsattributes.sip.in +++ b/python/core/auto_generated/qgsattributes.sip.in @@ -70,9 +70,12 @@ typedef QVector QgsAttributes; return 1; } - QgsAttributes *qv = new QgsAttributes; SIP_SSIZE_T listSize = PyList_GET_SIZE( sipPy ); - qv->resize( listSize ); + // Initialize attributes to null. This has two motivations: + // 1. It speeds up the QVector construction, as otherwise we are creating n default QVariant objects (default QVariant constructor is not free!) + // 2. It lets us shortcut in the loop below when a Py_None is encountered in the list + const QVariant nullVariant( QVariant::Int ); + QgsAttributes *qv = new QgsAttributes( listSize, nullVariant ); QVariant *outData = qv->data(); for ( SIP_SSIZE_T i = 0; i < listSize; ++i ) @@ -80,7 +83,8 @@ typedef QVector QgsAttributes; PyObject *obj = PyList_GET_ITEM( sipPy, i ); if ( obj == Py_None ) { - *outData++ = QVariant( QVariant::Int ); + // outData was already initialized to null values + *outData++; } else if ( PyBool_Check( obj ) ) { diff --git a/src/core/qgsattributes.h b/src/core/qgsattributes.h index 080b4c39e0c..7a9d1082f46 100644 --- a/src/core/qgsattributes.h +++ b/src/core/qgsattributes.h @@ -190,9 +190,12 @@ typedef QVector QgsAttributes; return 1; } - QgsAttributes *qv = new QgsAttributes; SIP_SSIZE_T listSize = PyList_GET_SIZE( sipPy ); - qv->resize( listSize ); + // Initialize attributes to null. This has two motivations: + // 1. It speeds up the QVector construction, as otherwise we are creating n default QVariant objects (default QVariant constructor is not free!) + // 2. It lets us shortcut in the loop below when a Py_None is encountered in the list + const QVariant nullVariant( QVariant::Int ); + QgsAttributes *qv = new QgsAttributes( listSize, nullVariant ); QVariant *outData = qv->data(); for ( SIP_SSIZE_T i = 0; i < listSize; ++i ) @@ -200,7 +203,8 @@ typedef QVector QgsAttributes; PyObject *obj = PyList_GET_ITEM( sipPy, i ); if ( obj == Py_None ) { - *outData++ = QVariant( QVariant::Int ); + // outData was already initialized to null values + *outData++; } else if ( PyBool_Check( obj ) ) {