From ade78ced6cfe4bd6f2174095e1913182485093d8 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 29 Apr 2011 18:47:47 +0200 Subject: [PATCH] substantially faster equality comparison for str and bytes in many cases --- Cython/Compiler/ExprNodes.py | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 7756b240..848a2f5a 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -6672,6 +6672,14 @@ class CmpNode(object): env.use_utility_code(pyunicode_equals_utility_code) self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" return True + elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type: + env.use_utility_code(pybytes_equals_utility_code) + self.special_bool_cmp_function = "__Pyx_PyBytes_Equals" + return True + elif type1 is Builtin.str_type or type2 is Builtin.str_type: + env.use_utility_code(pystr_equals_utility_code) + self.special_bool_cmp_function = "__Pyx_PyString_Equals" + return True return False def generate_operation_code(self, code, result_code, @@ -6884,6 +6892,49 @@ static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int } """) +pybytes_equals_utility_code = UtilityCode( +proto=""" +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/ +""", +impl=""" +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { + if (s1 == s2) { /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */ + return (equals == Py_EQ); + } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { + if (PyBytes_GET_SIZE(s1) != PyBytes_GET_SIZE(s2)) { + return (equals == Py_NE); + } else if (PyBytes_GET_SIZE(s1) == 1) { + if (equals == Py_EQ) + return (PyBytes_AS_STRING(s1)[0] == PyBytes_AS_STRING(s2)[0]); + else + return (PyBytes_AS_STRING(s1)[0] != PyBytes_AS_STRING(s2)[0]); + } + } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { + return (equals == Py_NE); + } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { + return (equals == Py_NE); + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +} +""") + +pystr_equals_utility_code = UtilityCode( +proto=""" +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals +#else +#define __Pyx_PyString_Equals __Pyx_PyBytes_Equals +#endif +""", +requires=[pybytes_equals_utility_code, pyunicode_equals_utility_code]) + class PrimaryCmpNode(ExprNode, CmpNode): # Non-cascaded comparison or first comparison of -- 2.26.2