This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author vstinner
Recipients malin, rhettinger, serhiy.storchaka, skrah, vstinner
Date 2019-03-20.23:36:13
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1553124973.68.0.841576701334.issue29301@roundup.psfhosted.org>
In-reply-to
Content
>  Also, the performance improvements are in argument parsing, but not when you have numerical code like a * b, where a and b are already decimals.

If the function call takes around 100 ns, the benefit of FASTCALL and the new more efficient function to parse arguments becomes quite significant. Some Decimal methods are that fast if not faster.

python3 -m perf timeit \
   -s 'import decimal; a=decimal.Decimal(1); b=decimal.Decimal(2); ctx=decimal.getcontext()' \
   'ctx.copy_sign(a, b)' \
   --duplicate=1024

=> Mean +- std dev: [ref] 148 ns +- 1 ns -> [fastcall] 98.9 ns +- 4.9 ns: 1.49x faster (-33%)

./python -m perf timeit \
   -s 'import decimal; a=decimal.Decimal(1); b=decimal.Decimal(2)' \
   'a.copy_sign(b)' \
   --duplicate=1024

=> Mean +- std dev: [ref] 123 ns +- 5 ns -> [fastcall] 86.5 ns +- 1.4 ns: 1.42x faster (-29%)

I wrote a quick & dirty change using directly METH_FASTCALL with _PyArg_ParseStackAndKeywords() (dec_mpd_qcopy_sign) and _PyArg_CheckPositional() (ctx_mpd_qcopy_sign). Using Argument Clinic may be more verbose, but it generates *even more* efficient code for functions accepting keyword arguments (like Decimal.copy_sign) and generate better docstring (at least, the signature for function parameters if no text is given).

Obviously, if your application only uses large numbers, the benefit will be invisible. But I guess that some people use decimal with "small" numbers ;-)

Note: Sure, you're right that operators like "a * b" wouldn't benefit from FASTCALL since they don't parse explicitly arguments. BINARY_MULTIPLY instruction gets directly 2 values from the Python stack and pass them to PyNumber_Multiply() with is defined to always take exactly 2 PyObject* in C.
History
Date User Action Args
2019-03-20 23:36:13vstinnersetrecipients: + vstinner, rhettinger, skrah, serhiy.storchaka, malin
2019-03-20 23:36:13vstinnersetmessageid: <1553124973.68.0.841576701334.issue29301@roundup.psfhosted.org>
2019-03-20 23:36:13vstinnerlinkissue29301 messages
2019-03-20 23:36:13vstinnercreate