From 339915a96269ffdd8f48335dda050f4aa071caed Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Jul 2015 09:58:10 +1000 Subject: Optimize PySequence_Fast usage Access arrays directly, avoiding type-check every time. --- source/blender/python/bmesh/bmesh_py_types.c | 3 ++- source/blender/python/generic/idprop_py_api.c | 17 +++++++++++------ source/blender/python/generic/py_capi_utils.c | 9 +++++---- source/blender/python/intern/bpy_interface.c | 4 +++- source/blender/python/intern/bpy_props.c | 3 ++- source/blender/python/intern/bpy_rna.c | 8 +++++--- source/blender/python/mathutils/mathutils.c | 11 +++++++---- source/blender/python/mathutils/mathutils_Matrix.c | 5 +++-- 8 files changed, 38 insertions(+), 22 deletions(-) (limited to 'source/blender/python') diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 1b2382831b1..e834c839552 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3766,6 +3766,7 @@ void *BPy_BMElem_PySeq_As_Array_FAST( const char *error_prefix) { BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL; + PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast); Py_ssize_t i; @@ -3785,7 +3786,7 @@ void *BPy_BMElem_PySeq_As_Array_FAST( alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **)); for (i = 0; i < seq_len; i++) { - item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i); + item = (BPy_BMElem *)seq_fast_items[i]; if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) { PyErr_Format(PyExc_TypeError, diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 30e0ccdb106..db8ed072722 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -299,12 +299,14 @@ static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item) /* returns NULL on success, error string on failure */ static char idp_sequence_type(PyObject *seq_fast) { + PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); PyObject *item; char type = IDP_INT; Py_ssize_t i, len = PySequence_Fast_GET_SIZE(seq_fast); + for (i = 0; i < len; i++) { - item = PySequence_Fast_GET_ITEM(seq_fast, i); + item = seq_fast_items[i]; if (PyFloat_Check(item)) { if (type == IDP_IDPARRAY) { /* mixed dict/int */ return -1; @@ -396,14 +398,17 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, //prop->subtype = IDP_STRING_SUB_BYTE; } else if (PySequence_Check(ob)) { - PyObject *ob_seq_fast = PySequence_Fast(ob, "py -> idprop"); + PyObject *ob_seq_fast; + PyObject **ob_seq_fast_items; PyObject *item; int i; - if (ob_seq_fast == NULL) { + if (!(ob_seq_fast = PySequence_Fast(ob, "py -> idprop"))) { return false; } + ob_seq_fast_items = PySequence_Fast_ITEMS(ob_seq_fast); + if ((val.array.type = idp_sequence_type(ob_seq_fast)) == (char)-1) { Py_DECREF(ob_seq_fast); PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays"); @@ -424,7 +429,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, prop = IDP_New(IDP_ARRAY, &val, name); prop_data = IDP_Array(prop); for (i = 0; i < val.array.len; i++) { - item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); + item = ob_seq_fast_items[i]; if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) { Py_DECREF(ob_seq_fast); return false; @@ -438,7 +443,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, prop = IDP_New(IDP_ARRAY, &val, name); prop_data = IDP_Array(prop); for (i = 0; i < val.array.len; i++) { - item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); + item = ob_seq_fast_items[i]; if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) { Py_DECREF(ob_seq_fast); return false; @@ -450,7 +455,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, { prop = IDP_NewIDPArray(name); for (i = 0; i < val.array.len; i++) { - item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); + item = ob_seq_fast_items[i]; if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) { Py_DECREF(ob_seq_fast); diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 17bd63bf5eb..d53e5629693 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -53,6 +53,7 @@ int PyC_AsArray_FAST( const PyTypeObject *type, const bool is_double, const char *error_prefix) { const Py_ssize_t value_len = PySequence_Fast_GET_SIZE(value_fast); + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); Py_ssize_t i; BLI_assert(PyList_Check(value_fast) || PyTuple_Check(value_fast)); @@ -69,13 +70,13 @@ int PyC_AsArray_FAST( if (is_double) { double *array_double = array; for (i = 0; i < length; i++) { - array_double[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i)); + array_double[i] = PyFloat_AsDouble(value_fast_items[i]); } } else { float *array_float = array; for (i = 0; i < length; i++) { - array_float[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i)); + array_float[i] = PyFloat_AsDouble(value_fast_items[i]); } } } @@ -83,13 +84,13 @@ int PyC_AsArray_FAST( /* could use is_double for 'long int' but no use now */ int *array_int = array; for (i = 0; i < length; i++) { - array_int[i] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)); + array_int[i] = PyLong_AsLong(value_fast_items[i]); } } else if (type == &PyBool_Type) { int *array_bool = array; for (i = 0; i < length; i++) { - array_bool[i] = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); + array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0); } } else { diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 7e5ad00159e..274b33558d3 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -742,9 +742,11 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * } else { int len = PySequence_Fast_GET_SIZE(seq_fast); + PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); int i; + for (i = 0; i < len; i++) { - PyObject *list_item = PySequence_Fast_GET_ITEM(seq_fast, i); + PyObject *list_item = seq_fast_items[i]; if (BPy_StructRNA_Check(list_item)) { #if 0 diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 4dcd642634a..6e70f97fd4e 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -1319,6 +1319,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i EnumPropertyItem *items; PyObject *item; const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast); + PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); Py_ssize_t totbuf = 0; int i; short def_used = 0; @@ -1366,7 +1367,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i Py_ssize_t name_str_size; Py_ssize_t desc_str_size; - item = PySequence_Fast_GET_ITEM(seq_fast, i); + item = seq_fast_items[i]; if ((PyTuple_CheckExact(item)) && (item_size = PyTuple_GET_SIZE(item)) && diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index af4b239d6e1..e74eaefc2b0 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -2637,6 +2637,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length, PyObject *value_orig) { PyObject *value; + PyObject **value_items; int count; void *values_alloc = NULL; int ret = 0; @@ -2658,6 +2659,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, return -1; } + value_items = PySequence_Fast_ITEMS(value); switch (RNA_property_type(prop)) { case PROP_FLOAT: { @@ -2673,7 +2675,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, RNA_property_float_get_array(ptr, prop, values); for (count = start; count < stop; count++) { - fval = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, count - start)); + fval = PyFloat_AsDouble(value_items[count - start]); CLAMP(fval, min, max); values[count] = fval; } @@ -2693,7 +2695,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, RNA_property_boolean_get_array(ptr, prop, values); for (count = start; count < stop; count++) - values[count] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value, count - start)); + values[count] = PyLong_AsLong(value_items[count - start]); if (PyErr_Occurred()) ret = -1; else RNA_property_boolean_set_array(ptr, prop, values); @@ -2714,7 +2716,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, RNA_property_int_get_array(ptr, prop, values); for (count = start; count < stop; count++) { - ival = PyLong_AsLong(PySequence_Fast_GET_ITEM(value, count - start)); + ival = PyLong_AsLong(value_items[count - start]); CLAMP(ival, min, max); values[count] = ival; } diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 4a2d9cfe99b..ba7f351996a 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -57,20 +57,22 @@ static int mathutils_array_parse_fast(float *array, const char *error_prefix) { PyObject *item; + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); int i; i = size; do { i--; - if (((array[i] = PyFloat_AsDouble((item = PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) && + if (((array[i] = PyFloat_AsDouble((item = value_fast_items[i]))) == -1.0f) && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "%.200s: sequence index %d expected a number, " "found '%.200s' type, ", error_prefix, i, Py_TYPE(item)->tp_name); - return -1; + size = -1; + break; } } while (i); @@ -261,7 +263,7 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c /* parse an array of vectors */ int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix) { - PyObject *value_fast = NULL; + PyObject *value_fast; const int array_dim_flag = array_dim; int i, size; @@ -274,6 +276,7 @@ int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, size = PySequence_Fast_GET_SIZE(value_fast); if (size != 0) { + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); float *fp; array_dim &= ~MU_ARRAY_FLAGS; @@ -281,7 +284,7 @@ int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, fp = *array = PyMem_Malloc(size * array_dim * sizeof(float)); for (i = 0; i < size; i++, fp += array_dim) { - PyObject *item = PySequence_Fast_GET_ITEM(value, i); + PyObject *item = value_fast_items[i]; if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) { PyMem_Free(*array); diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index e0de5ddbdc0..41baa9b089f 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -2188,7 +2188,7 @@ static PyObject *Matrix_slice(MatrixObject *self, int begin, int end) * sequence slice (set)*/ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value) { - PyObject *value_fast = NULL; + PyObject *value_fast; if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; @@ -2203,6 +2203,7 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va return -1; } else { + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); const int size = end - begin; int row, col; float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; @@ -2221,7 +2222,7 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va /* parse sub items */ for (row = begin; row < end; row++) { /* parse each sub sequence */ - PyObject *item = PySequence_Fast_GET_ITEM(value_fast, row - begin); + PyObject *item = value_fast_items[row - begin]; if (mathutils_array_parse(vec, self->num_col, self->num_col, item, "matrix[begin:end] = value assignment") == -1) -- cgit v1.2.3