<div dir="ltr">Hi Ben,<div><br></div><div>for what you're interested in, you might give a look at WPython 1.0 ( <a href="https://code.google.com/archive/p/wpython/downloads">https://code.google.com/archive/p/wpython/downloads</a> ) and 1.1 ( <a href="https://code.google.com/archive/p/wpython2/downloads">https://code.google.com/archive/p/wpython2/downloads</a> ), but they cover a lot of optimizations (as you can see from a brief look at the slides): RETURN_CONST and fusing some opcodes for binary operations are only some of them.</div><div>For this reason, it's also very difficult to micro-benchmark every single change... :-/</div><div><br></div><div>Cheers,</div><div>Cesare</div></div><div id="DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2"><br> <table style="border-top:1px solid #d3d4de">
        <tr>
      <td style="width:55px;padding-top:18px"><a href="https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail" target="_blank"><img src="https://ipmcdn.avast.com/images/icons/icon-envelope-tick-round-orange-animated-no-repeat-v1.gif" alt="" width="46" height="29" style="width: 46px; height: 29px;"></a></td>
                <td style="width:470px;padding-top:17px;color:#41424e;font-size:13px;font-family:Arial,Helvetica,sans-serif;line-height:18px">Mail priva di virus. <a href="https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail" target="_blank" style="color:#4453ea">www.avast.com</a>          </td>
        </tr>
</table>
<a href="#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2" width="1" height="1"></a></div><div class="gmail_extra"><br><div class="gmail_quote">2017-05-25 16:28 GMT+02:00 Ben Hoyt <span dir="ltr"><<a href="mailto:benhoyt@gmail.com" target="_blank">benhoyt@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">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.<div><br></div><div>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:</div><div><br></div><div><div>LOAD_CONST(None)</div><div>COMPARE_OP</div><div>    PyObject *value = ((PyTupleObject *)(consts))->ob_item[oparg];</div><div>    value->ob_refcnt++;</div><div>    *stack_pointer++ = value;</div><div>    FAST_DISPATCH();</div><div>    PyObject *right = *--stack_pointer;</div><div>    PyObject *left = stack_pointer[-1]</div><div><br></div><div>    // cmp_outcome(), presumably inlined</div><div>    int r = 0;</div><div>    switch (compare_oparg) {</div><div>    case PyCmp_IS:</div><div>        r = (left == right);</div><div>        break;</div><div>    case PyCmp_IS_NOT:</div><div>        r = (left != right);</div><div>        break;</div><div>    case ...</div><div>    }</div><div>    PyObject *res = r ? Py_True : Py_False;</div><div>    res->ob_refcnt++;</div><div><br></div><div>    if (--(left)->ob_refcnt == 0)</div><div>        _Py_Dealloc(left);</div><div>    if (--(right)->ob_refcnt == 0)</div><div>        _Py_Dealloc(right);</div><div>    stack_pointer[-1] = res;</div><div>    if (res == NULL)</div><div>        goto error;</div><div><br></div><div>    PREDICT(POP_JUMP_IF_FALSE);</div><div>    PREDICT(POP_JUMP_IF_TRUE);</div><div>    DISPATCH();</div><div><br></div><div><br></div><div>COMPARE_IS_NONE</div><div>    PyObject* left = stack_pointer[-1];  // TOP()</div><div>    PyObject* res = (left == Py_None) ? Py_True : Py_False;</div><div>    res->ob_refcnt++;</div><div>    if (--(left)->ob_refcnt == 0)</div><div>        _Py_Dealloc(left);</div><div>    stack_pointer[-1] = res;  // SET_TOP(res)</div><div>    PREDICT(POP_JUMP_IF_FALSE);</div><div>    PREDICT(POP_JUMP_IF_TRUE);</div><div>    DISPATCH();</div></div><div><br></div><div>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).</div><div><br></div><div>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).</div><div><br></div><div>Still, the performance proof will be in the pudding! I might hack these two opcodes together and test it at some point.<span class="HOEnZb"><font color="#888888"><br><div><br></div><div>-Ben</div></font></span></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, May 25, 2017 at 6:47 AM, Victor Stinner <span dir="ltr"><<a href="mailto:victor.stinner@gmail.com" target="_blank">victor.stinner@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">Hi Ben,<div dir="auto"><br></div><div dir="auto">I am not convinced that combining operations will have a significant impact in term of performance. Mark Shanon implemented that in his HotPy project.</div><div dir="auto"><br></div><div dir="auto">I proposed a RETURN_NONE opcode to combine LOAD_CONST with RETURN_VALUE. The issue was rejected because I failed to show any speedup.</div><div dir="auto"><br></div><div dir="auto"><a href="https://bugs.python.org/issue28800" target="_blank">https://bugs.python.org/issue2<wbr>8800</a><br></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto"><a href="http://faster-cpython.readthedocs.io/registervm.html" target="_blank">http://faster-cpython.readthed<wbr>ocs.io/registervm.html</a><br></div><div dir="auto"><br></div><div dir="auto">Mark's bytecode uses registers but also a stack.</div><div dir="auto"><br></div><div dir="auto">Victor</div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="m_7873767691472963090h5">Le 24 mai 2017 8:09 PM, "Ben Hoyt" <<a href="mailto:benhoyt@gmail.com" target="_blank">benhoyt@gmail.com</a>> a écrit :<br type="attribution"></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="m_7873767691472963090h5"><div dir="ltr"><div>Hi folks,</div><div><br></div><div>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?</div><div><br></div><div>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).</div><div><br></div><div>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?</div><div><br></div><div>Thanks,</div><div>Ben</div><div><br></div></div>
<br></div></div><span>______________________________<wbr>_________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org" target="_blank">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailma<wbr>n/listinfo/python-dev</a><br></span>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/victor.stinner%40gmail.com" rel="noreferrer" target="_blank">https://mail.python.org/mailma<wbr>n/options/python-dev/victor.st<wbr>inner%40gmail.com</a><br>
<br></blockquote></div></div>
</blockquote></div><br></div>
</div></div><br>______________________________<wbr>_________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/cesare.di.mauro%40gmail.com" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/options/python-dev/<wbr>cesare.di.mauro%40gmail.com</a><br>
<br></blockquote></div><br></div>