int.__mul__ , executes 2X slower than operator.mul

前端 未结 1 1455
小鲜肉
小鲜肉 2020-12-30 05:22

If you look at the following timings:

C:\\Users\\Henry>python -m timeit -s \"mul = int.__mul__\" \"reduce(mul,range(10000))\"
1000 loops, best of 3: 908 u         


        
相关标签:
1条回答
  • 2020-12-30 05:57

    int.__mul__ is a slot wrapper, namely, a PyWrapperDescrObject, while operator.mul is a buit-in function. I think the opposite execution speed is caused by this difference.

    >>> int.__mul__
    <slot wrapper '__mul__' of 'int' objects>
    >>> operator.mul
    <built-in function mul>
    

    When we call a PyWrapperDescrObject, wrapperdescr_call is called.

    
    static PyObject *
    wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
    {
        Py_ssize_t argc;
        PyObject *self, *func, *result;
    
        /* Make sure that the first argument is acceptable as 'self' */
        assert(PyTuple_Check(args));
        argc = PyTuple_GET_SIZE(args);
        if (argc d_type->tp_name);
            return NULL;
        }
        self = PyTuple_GET_ITEM(args, 0);
        if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
                                      (PyObject *)(descr->d_type))) {
            PyErr_Format(PyExc_TypeError,
                         "descriptor '%.200s' "
                         "requires a '%.100s' object "
                         "but received a '%.100s'",
                         descr_name((PyDescrObject *)descr),
                         descr->d_type->tp_name,
                         self->ob_type->tp_name);
            return NULL;
        }
    
        func = PyWrapper_New((PyObject *)descr, self);
        if (func == NULL)
            return NULL;
        args = PyTuple_GetSlice(args, 1, argc);
        if (args == NULL) {
            Py_DECREF(func);
            return NULL;
        }
        result = PyEval_CallObjectWithKeywords(func, args, kwds);
        Py_DECREF(args);
        Py_DECREF(func);
        return result;
    }
    

    Let us look at what we found!

    func = PyWrapper_New((PyObject *)descr, self);
    

    A new PyWrapper object has been constructed. It would slow down the execution speed significantly. Sometimes, it takes more time to create a new object than to run a simple function.
    Thus, it is not surprised that int.__mul__ is slower than operator.mul.

    0 讨论(0)
提交回复
热议问题