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
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"
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@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/victor. stinner%40gmail.com