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
Attached patch is a work-in-progress patch to use the new private _PyBytesWriter API in bytes % args.
The usage of the _PyBytesWriter API will allow further optimization. For example, it avoids the creation of a temporary bytes object to format b'%f' % 1.2.
The _PyBytesWriter API allocates a small buffer of 512 bytes on the stack to delay the allocation of the final bytes objects. It can avoid the need to call _PyBytes_Resize() completly, or at least reduce the number of calls.
See also the issue bpo-25318 which added the _PyBytesWriter API.
bench_bytes_format.py: micro-benchmark testing a few formats. Some tests are focused on the implementation of _PyBytesWriter to ensure that the optimization is efficient.
Except of a single test (which is not really revelant, it takes less than 500 nanoseconds), all tests are faster.
The b"xxxxxx %s" % b"y" test confirms that the optimization disabling overallocation for the last write is effective.
bytes_formatlong.patch: Fast-path for b'%d' % int and other integer formatters. It avoids the creation of a temporary bytes object, it writes directly into the writer, as '%d' % int (Unicode).
Total | 1.86 us (*) | 1.67 us (-10%)
----------------------------------------------+-------------+---------------
-------------------+-------------+---------------
Summary | orig | writer
-------------------+-------------+---------------
%i | 83.6 us () | 42.9 us (-49%)
x=%i | 90.8 us () | 50.7 us (-44%)
%x | 82.8 us () | 41.9 us (-49%)
x=%x | 98.6 us () | 58.5 us (-41%)
large int: %i | 3.14 us () | 2.9 us (-8%)
large int: x=%i | 1.86 us () | 1.67 us (-10%)
-------------------+-------------+---------------
Total | 363 us (*) | 201 us (-45%)
-------------------+-------------+---------------
Activity
vstinner commentedon Oct 9, 2015
Attached patch is a work-in-progress patch to use the new private _PyBytesWriter API in bytes % args.
The usage of the _PyBytesWriter API will allow further optimization. For example, it avoids the creation of a temporary bytes object to format b'%f' % 1.2.
The _PyBytesWriter API allocates a small buffer of 512 bytes on the stack to delay the allocation of the final bytes objects. It can avoid the need to call _PyBytes_Resize() completly, or at least reduce the number of calls.
See also the issue bpo-25318 which added the _PyBytesWriter API.
vstinner commentedon Oct 9, 2015
See also the PEP-461 "Adding % formatting to bytes and bytearray".
FYI bytes % args is tested by test_format (good to know to test quickly changes).
vstinner commentedon Oct 9, 2015
bench_bytes_format.py: micro-benchmark testing a few formats. Some tests are focused on the implementation of _PyBytesWriter to ensure that the optimization is efficient.
Except of a single test (which is not really revelant, it takes less than 500 nanoseconds), all tests are faster.
The b"xxxxxx %s" % b"y" test confirms that the optimization disabling overallocation for the last write is effective.
Results:
Common platform:
Timer info: namespace(adjustable=False, implementation='clock_gettime(CLOCK_MONOTONIC)', monotonic=True, resolution=1e-09)
Python unicode implementation: PEP-393
CPU model: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
Platform: Linux-4.1.6-200.fc22.x86_64-x86_64-with-fedora-22-Twenty_Two
CFLAGS: -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
Timer: time.perf_counter
Bits: int=32, long=64, long long=64, size_t=64, void*=64
Platform of campaign orig:
SCM: hg revision=1aae9b6a6929 tag=tip branch=default date="2015-10-09 01:34 -0400"
Timer precision: 64 ns
Python version: 3.6.0a0 (default:1aae9b6a6929, Oct 9 2015, 11:33:56) [GCC 5.1.1 20150618 (Red Hat 5.1.1-4)]
Date: 2015-10-09 11:34:11
Platform of campaign writer:
SCM: hg revision=fc2c11a19ae1+ tag=tip branch=default date="2015-10-09 11:48 +0200"
Timer precision: 61 ns
Python version: 3.6.0a0 (default:fc2c11a19ae1+, Oct 9 2015, 12:16:16) [GCC 5.1.1 20150618 (Red Hat 5.1.1-4)]
Date: 2015-10-09 12:16:31
---------------------------+------------+--------------
use smaller buffer | orig | writer
---------------------------+------------+--------------
b"hello %s" % b"world" | 13 ns () | 12 ns (-5%)
b"hello %-100s" % b"world" | 158 ns () | 98 ns (-38%)
b"x=%d" % 123 | 13 ns () | 12 ns
b"x=%f" % 1.2 | 13 ns () | 13 ns
b"x=%100d" % 123 | 156 ns () | 166 ns (+7%)
---------------------------+------------+--------------
Total | 353 ns () | 301 ns (-15%)
---------------------------+------------+--------------
-------------------------------------------------+-------------+---------------
"hello %s" % long_string | orig | writer
-------------------------------------------------+-------------+---------------
Total | 5.28 us (*) | 4.77 us (-10%)
-------------------------------------------------+-------------+---------------
---------------------------------------+-------------+---------------
b"xxxxxx %s" % b"y" | orig | writer
---------------------------------------+-------------+---------------
Total | 89.8 us (*) | 8.87 us (-90%)
---------------------------------------+-------------+---------------
----------------------------------------------------------+-------------+---------------
%f | orig | writer
----------------------------------------------------------+-------------+---------------
------------------------------------------------------------+-------------+---------------
%i | orig | writer
------------------------------------------------------------+-------------+---------------
-------------------------+-------------+---------------
Summary | orig | writer
-------------------------+-------------+---------------
use smaller buffer | 353 ns () | 301 ns (-15%)
"hello %s" % long_string | 5.28 us () | 4.77 us (-10%)
b"xxxxxx %s" % b"y" | 89.8 us () | 8.87 us (-90%)
%f | 37.2 us () | 29.6 us (-21%)
%i | 49.4 us () | 42.8 us (-13%)
-------------------------+-------------+---------------
Total | 182 us () | 86.3 us (-53%)
-------------------------+-------------+---------------
python-dev commentedon Oct 9, 2015
New changeset b2f3cbdc0f2d by Victor Stinner in branch 'default':
Issue bpo-25349: Optimize bytes % args using the new private _PyBytesWriter API
https://hg.python.org/cpython/rev/b2f3cbdc0f2d
vstinner commentedon Oct 9, 2015
bytes_formatlong.patch: Fast-path for b'%d' % int and other integer formatters. It avoids the creation of a temporary bytes object, it writes directly into the writer, as '%d' % int (Unicode).
vstinner commentedon Oct 9, 2015
I wrote bench_bytes_int.py micro-benchmark, results are below.
Oh, I did'n expected a real difference even for simple code like b'%d' % 12345 (32% faster). So I consider that it's enough to apply the optimization.
Common platform:
Timer: time.perf_counter
Bits: int=32, long=64, long long=64, size_t=64, void*=64
CPU model: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
Platform: Linux-4.1.6-200.fc22.x86_64-x86_64-with-fedora-22-Twenty_Two
Python unicode implementation: PEP-393
Timer info: namespace(adjustable=False, implementation='clock_gettime(CLOCK_MONOTONIC)', monotonic=True, resolution=1e-09)
CFLAGS: -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
Platform of campaign orig:
SCM: hg revision=576128c0d068 tag=tip branch=default date="2015-10-09 10:20 -0400"
Python version: 3.6.0a0 (default:576128c0d068, Oct 9 2015, 22:36:21) [GCC 5.1.1 20150618 (Red Hat 5.1.1-4)]
Date: 2015-10-09 22:36:36
Timer precision: 62 ns
Platform of campaign writer:
Python version: 3.6.0a0 (default:576128c0d068+, Oct 9 2015, 22:28:09) [GCC 5.1.1 20150618 (Red Hat 5.1.1-4)]
Date: 2015-10-09 22:34:53
SCM: hg revision=576128c0d068+ tag=tip branch=default date="2015-10-09 10:20 -0400"
Timer precision: 65 ns
------------------------------------------------------------+-------------+---------------
%i | orig | writer
------------------------------------------------------------+-------------+---------------
Total | 83.6 us (*) | 42.9 us (-49%)
------------------------------------------------------------+-------------+---------------
---------------------------------------------------------------+-------------+---------------
x=%i | orig | writer
---------------------------------------------------------------+-------------+---------------
Total | 90.8 us (*) | 50.7 us (-44%)
---------------------------------------------------------------+-------------+---------------
------------------------------------------------------------+-------------+---------------
%x | orig | writer
------------------------------------------------------------+-------------+---------------
Total | 82.8 us (*) | 41.9 us (-49%)
------------------------------------------------------------+-------------+---------------
------------------------------------------------------------------+-------------+---------------
x=%x | orig | writer
------------------------------------------------------------------+-------------+---------------
Total | 98.6 us (*) | 58.5 us (-41%)
------------------------------------------------------------------+-------------+---------------
--------------------------------------------+-------------+--------------
large int: %i | orig | writer
--------------------------------------------+-------------+--------------
Total | 3.14 us (*) | 2.9 us (-8%)
--------------------------------------------+-------------+--------------
----------------------------------------------+-------------+---------------
large int: x=%i | orig | writer
----------------------------------------------+-------------+---------------
Total | 1.86 us (*) | 1.67 us (-10%)
----------------------------------------------+-------------+---------------
-------------------+-------------+---------------
Summary | orig | writer
-------------------+-------------+---------------
%i | 83.6 us () | 42.9 us (-49%)
x=%i | 90.8 us () | 50.7 us (-44%)
%x | 82.8 us () | 41.9 us (-49%)
x=%x | 98.6 us () | 58.5 us (-41%)
large int: %i | 3.14 us () | 2.9 us (-8%)
large int: x=%i | 1.86 us () | 1.67 us (-10%)
-------------------+-------------+---------------
Total | 363 us (*) | 201 us (-45%)
-------------------+-------------+---------------
python-dev commentedon Oct 9, 2015
New changeset d9a89c9137d2 by Victor Stinner in branch 'default':
Issue bpo-25349: Optimize bytes % int
https://hg.python.org/cpython/rev/d9a89c9137d2
New changeset 4d46d1588629 by Victor Stinner in branch 'default':
Issue bpo-25349: Add fast path for b'%c' % int
https://hg.python.org/cpython/rev/4d46d1588629
vstinner commentedon Oct 9, 2015
Ok, I implemented all optimizations which were already implemented in str % args. I close the issue.
python-dev commentedon Apr 26, 2016
New changeset 090502a0c69c by Victor Stinner in branch 'default':
Issue bpo-25349, bpo-26249: Fix memleak in formatfloat()
https://hg.python.org/cpython/rev/090502a0c69c