python - int.__mul__ , executes 2X slower than operator.mul -
if @ following timings:
c:\users\henry>python -m timeit -s "mul = int.__mul__" "reduce(mul,range(10000))" 1000 loops, best of 3: 908 usec per loop c:\users\henry>python -m timeit -s "from operator import mul" "reduce(mul,range(10000))" 1000 loops, best of 3: 410 usec per loop
there significant difference in execution speed between
reduce(int.__mul__,range(10000))
, reduce(mul,range(10000))
latter being faster.
using dis
module @ happening:
using int.__mul__
method:
c:\users\henry>python python 2.7.4 (default, apr 6 2013, 19:55:15) [msc v.1500 64 bit (amd64)] on win32 type "help", "copyright", "credits" or "license" more information. >>> mul = int.__mul__ >>> def test(): ... mul(1,2) ... >>> import dis >>> dis.dis(test) 2 0 load_global 0 (mul) 3 load_const 1 (1) 6 load_const 2 (2) 9 call_function 2 12 pop_top 13 load_const 0 (none) 16 return_value >>>
and operator mul
method
c:\users\henry>python python 2.7.4 (default, apr 6 2013, 19:55:15) [msc v.1500 64 bit (amd64)] on win32 type "help", "copyright", "credits" or "license" more information. >>> operator import mul >>> def test(): ... mul(1,2) ... >>> import dis >>> dis.dis(test) 2 0 load_global 0 (mul) 3 load_const 1 (1) 6 load_const 2 (2) 9 call_function 2 12 pop_top 13 load_const 0 (none) 16 return_value >>>
they appear same, why there difference in execution speed? referring cpython implementation of python
the same happens on python3:
$ python3 -m timeit -s 'mul=int.__mul__;from functools import reduce' 'reduce(mul, range(10000))' 1000 loops, best of 3: 1.18 msec per loop $ python3 -m timeit -s 'from operator import mul;from functools import reduce' 'reduce(mul, range(10000))' 1000 loops, best of 3: 643 usec per loop $ python3 -m timeit -s 'mul=lambda x,y:x*y;from functools import reduce' 'reduce(mul, range(10000))' 1000 loops, best of 3: 1.26 msec per loop
int.__mul__
slot wrapper, namely, pywrapperdescrobject, while operator.mul
buit-in function. think opposite execution speed caused difference.
>>> int.__mul__ <slot wrapper '__mul__' of 'int' objects> >>> operator.mul <built-in function mul>
when call pywrapperdescrobject, wrapperdescr_call
called.
static pyobject * wrapperdescr_call(pywrapperdescrobject *descr, pyobject *args, pyobject *kwds) { py_ssize_t argc; pyobject *self, *func, *result; /* make sure first argument acceptable '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 '%.100s' object " "but received '%.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 @ found!
func = pywrapper_new((pyobject *)descr, self);
a new pywrapper object has been constructed. slow down execution speed significantly. sometimes, takes more time create new object run simple function.
thus, not surprised int.__mul__
slower operator.mul
.
Comments
Post a Comment