[Python-Dev] Micro-optimizations by adding special-case bytecodes?
Ben Hoyt
benhoyt at gmail.com
Thu May 25 10:28:11 EDT 2017
Thanks, Victor. That's very helpful. So RETURN_NONE (and probably
RETURN_SMALL_CONST) are not worth it, based on your empirical tests. Your
patch shows how (relatively) straight-forward it is to test out new opcodes.
I'm still optimistic about the value of COMPARE_IS_NONE and
COMPARE_IS_NOT_NONE, though. Mainly because I've done a quick expansion of
LOAD_CONST(None) + COMPARE_OP and it's quite a bit more code and many more
instructions than COMPARE_IS_NONE would be:
LOAD_CONST(None)
COMPARE_OP
PyObject *value = ((PyTupleObject *)(consts))->ob_item[oparg];
value->ob_refcnt++;
*stack_pointer++ = value;
FAST_DISPATCH();
PyObject *right = *--stack_pointer;
PyObject *left = stack_pointer[-1]
// cmp_outcome(), presumably inlined
int r = 0;
switch (compare_oparg) {
case PyCmp_IS:
r = (left == right);
break;
case PyCmp_IS_NOT:
r = (left != right);
break;
case ...
}
PyObject *res = r ? Py_True : Py_False;
res->ob_refcnt++;
if (--(left)->ob_refcnt == 0)
_Py_Dealloc(left);
if (--(right)->ob_refcnt == 0)
_Py_Dealloc(right);
stack_pointer[-1] = res;
if (res == NULL)
goto error;
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
COMPARE_IS_NONE
PyObject* left = stack_pointer[-1]; // TOP()
PyObject* res = (left == Py_None) ? Py_True : Py_False;
res->ob_refcnt++;
if (--(left)->ob_refcnt == 0)
_Py_Dealloc(left);
stack_pointer[-1] = res; // SET_TOP(res)
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
You don't have to get the const arg, there are fewer increfs/decrefs, you
skip a pop, you don't have to test res==NULL (because it's Py_True or
Py_False, which are never NULL), and if there are separate COMPARE_IS_NONE
and COMPARE_IS_NOT_NONE you don't have to switch on the compare arg (though
I'm not sure if that part will be worth it).
For reference, based on a grep, " is None" occurs 2737 times in the CPython
source tree, and " is not None" 2010 times. And I know personally I often
use them in loops as well is at the start of functions (for mutable default
arg handling).
Still, the performance proof will be in the pudding! I might hack these two
opcodes together and test it at some point.
-Ben
On Thu, May 25, 2017 at 6:47 AM, Victor Stinner <victor.stinner at gmail.com>
wrote:
> Hi Ben,
>
> I am not convinced that combining operations will have a significant
> impact in term of performance. Mark Shanon implemented that in his HotPy
> project.
>
> I proposed a RETURN_NONE opcode to combine LOAD_CONST with RETURN_VALUE.
> The issue was rejected because I failed to show any speedup.
>
> https://bugs.python.org/issue28800
>
> I would be interested to restart/finish my registervm project to use
> register-based bytecode. It allows to implement more optmisations and
> reduce the number of instructions. In my experience, less instructions =
> faster code.
>
> http://faster-cpython.readthedocs.io/registervm.html
>
> Mark's bytecode uses registers but also a stack.
>
> Victor
>
> Le 24 mai 2017 8:09 PM, "Ben Hoyt" <benhoyt at gmail.com> a écrit :
>
>> Hi folks,
>>
>> I was looking at some `dis` output today, and I was wondering if anyone
>> has investigated optimizing Python (slightly) by adding special-case
>> bytecodes for common expressions or statements involving constants?
>>
>> For example, I (and, based on a quick grep of the stdlib, many others)
>> write "x is None" and "x is not None" very often. Or "return True" or
>> "return None" or "return 1" and things like that. These all expand into two
>> bytecodes, which seems pretty non-optimal (LOAD_CONST + COMPARE_OP or
>> LOAD_CONST + RETURN_VALUE). It seems we could get an easy speedup for these
>> common cases by adding a peephole optimization and some new opcodes (maybe
>> COMPARE_IS_SMALL_CONST and RETURN_SMALL_CONST for these cases).
>>
>> I'm not proposing to do this yet, as I'd need to benchmark to see how
>> much of a gain (if any) it would amount to, but I'm just wondering if
>> there's any previous work on this kind of thing. Or, if not, any other
>> thoughts before I try it?
>>
>> Thanks,
>> Ben
>>
>>
>> _______________________________________________
>> Python-Dev mailing list
>> Python-Dev at python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe: https://mail.python.org/mailman/options/python-dev/victor.
>> stinner%40gmail.com
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20170525/1553340e/attachment.html>
More information about the Python-Dev
mailing list