You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Avoid nonneeded use of PyUnicode_FromObject() #70245
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee='https://github.com/serhiy-storchaka'closed_at=<Date2016-04-13.12:45:58.826>created_at=<Date2016-01-09.08:41:41.041>labels= ['interpreter-core', 'type-feature']
title='Avoid nonneeded use of PyUnicode_FromObject()'updated_at=<Date2016-04-14.09:31:23.514>user='https://github.com/serhiy-storchaka'
In Python 2 PyUnicode_FromObject() was used for coercing 8-bit strings to unicode by decoding them with the default encoding. But in Python 3 there is no such coercing. The effect of PyUnicode_FromObject() in Python 3 is ensuring that the argument is a string and convert an instance of str subtype to exact str. The latter often is just a waste of memory and time, since resulted string is used only for retrieving UTF-8 representation or raw data.
Proposed patch makes following things:
Avoids unneeded copying of string's content.
Avoids raising some unneeded exceptions.
Gets rid of unneeded incref/decref.
Makes some error messages more correct or informative.
Converts runtime checks PyBytes_Check() for results of string encoding to asserts.
Example of performance gain:
Unpatched:
$ ./python -m timeit -s "a = 'a'*100; b = 'b'*1000" -- "a in b"
1000000 loops, best of 3: 0.404 usec per loop
$ ./python -m timeit -s "class S(str): pass" -s "a = S('a'*100); b = S('b'*1000)" -- "a in b"
1000000 loops, best of 3: 0.723 usec per loop
Patched:
$ ./python -m timeit -s "a = 'a'*100; b = 'b'*1000" -- "a in b"
1000000 loops, best of 3: 0.383 usec per loop
$ ./python -m timeit -s "class S(str): pass" -s "a = S('a'*100); b = S('b'*1000)" -- "a in b"
1000000 loops, best of 3: 0.387 usec per loop
Activity
serhiy-storchaka commentedon Jan 9, 2016
In Python 2 PyUnicode_FromObject() was used for coercing 8-bit strings to unicode by decoding them with the default encoding. But in Python 3 there is no such coercing. The effect of PyUnicode_FromObject() in Python 3 is ensuring that the argument is a string and convert an instance of str subtype to exact str. The latter often is just a waste of memory and time, since resulted string is used only for retrieving UTF-8 representation or raw data.
Proposed patch makes following things:
Example of performance gain:
Unpatched:
$ ./python -m timeit -s "a = 'a'*100; b = 'b'*1000" -- "a in b"
1000000 loops, best of 3: 0.404 usec per loop
$ ./python -m timeit -s "class S(str): pass" -s "a = S('a'*100); b = S('b'*1000)" -- "a in b"
1000000 loops, best of 3: 0.723 usec per loop
Patched:
$ ./python -m timeit -s "a = 'a'*100; b = 'b'*1000" -- "a in b"
1000000 loops, best of 3: 0.383 usec per loop
$ ./python -m timeit -s "class S(str): pass" -s "a = S('a'*100); b = S('b'*1000)" -- "a in b"
1000000 loops, best of 3: 0.387 usec per loop
serhiy-storchaka commentedon Jan 9, 2016
See also bpo-15984 about correcting the documentation of PyUnicode_FromObject().
vadmium commentedon Apr 10, 2016
Left some comments
serhiy-storchaka commentedon Apr 10, 2016
Updated patch addresses Martin's comments.
vadmium commentedon Apr 13, 2016
Apart from one redundancy (see review), this looks good to me.
python-dev commentedon Apr 13, 2016
New changeset 3f3b3d4881f6 by Serhiy Storchaka in branch 'default':
Issue bpo-26057: Got rid of nonneeded use of PyUnicode_FromObject().
https://hg.python.org/cpython/rev/3f3b3d4881f6
serhiy-storchaka commentedon Apr 13, 2016
Thank you for your review Martin.
python-dev commentedon Apr 14, 2016
New changeset 19dec08e54a8 by Serhiy Storchaka in branch 'default':
Issues bpo-26716, bpo-26057: Regenerate Argument Clinic code.
https://hg.python.org/cpython/rev/19dec08e54a8