Author Oren Milman
Recipients Oren Milman, serhiy.storchaka, vstinner
Date 2016-07-08.14:43:15
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1467988996.21.0.860681274549.issue27441@psf.upfronthosting.co.za>
In-reply-to
Content
I am sorry, but I can't see why micro-benchmarking is needed here, as my patches only remove code that does nothing, while they don't add any new code.

The assembly the compiler generates (on my PC) for 'Py_SIZE(v) = negative ? -ndigits : ndigits;' in PyLong_FromLongLong is: 
('[edx+8]' is 'Py_SIZE(v)',
 '[esp+10h+var_4]' is 'negative',
  The 'lea ecx, [edx+0Ch]' and 'mov eax, edi' instructions set ecx and eax for later (I haven't removed them in order to be as precise as possible.))
    ...
    cmp     [esp+10h+var_4], 0
    lea     ecx, [edx+0Ch]
    jz      short loc_1E0D48EC
        neg     ebx
loc_1E0D48EC:
    mov     eax, edi
    mov     [edx+8], ebx
    ...
In contrast, the assembly the compiler generates for 'if (negative) Py_SIZE(v) = -ndigits;' is:
    ...
    cmp     [esp+10h+var_4], 0
    lea     ecx, [edx+0Ch]
    jz      short loc_1E0D482F
        neg     ebx
        mov     [edx+8], ebx
loc_1E0D482F:
    mov     eax, edi
    ...
Comparing the assembly generated for the other original '?:' expressions with my corresponding patches looks quite the same. Each patch moves the assignment from code which is executed in both of the flows, to code which is executed in only one of the flows.

Am I missing anything that might cause my patches to introduce a performance penalty?


I searched (all of the cpython repo) for other places in which Py_SIZE() is set to the same value, and indeed found one in Objects/longobject.c in _PyLong_Init:
The loop that initializes the small_ints array goes over every element in the array, and checks whether it was already initialized. For some reason, even when it realizes the current element was already initialized, it still sets 'Py_SIZE(v)' and 'v->ob_digit[0]' (to the values they are already set to).
These redundant assignments were first added in changeset 45072 (https://hg.python.org/cpython/rev/f183f1189824), and remained there to this day.

So I added a patch to move these assignments so they would be executed only in case the current element of small_ints wasn't already initialized.
The updated patches diff file is attached. I also ran the tests again, and got quite the same output (the output is attached).

Have you spotted any other places in which Py_SIZE() is set to the same value?
History
Date User Action Args
2016-07-08 14:43:16Oren Milmansetrecipients: + Oren Milman, vstinner, serhiy.storchaka
2016-07-08 14:43:16Oren Milmansetmessageid: <1467988996.21.0.860681274549.issue27441@psf.upfronthosting.co.za>
2016-07-08 14:43:16Oren Milmanlinkissue27441 messages
2016-07-08 14:43:16Oren Milmancreate