diff options
author | sweeneyde <36520290+sweeneyde@users.noreply.github.com> | 2020-04-21 00:17:52 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-21 00:17:52 (GMT) |
commit | 6a9e80a93148b13e4d3bceaab5ea1804ab0e64d5 (patch) | |
tree | 5bffbbd4b19aac9be793326c8324f057fedcaa40 | |
parent | bba760e9b6c7da3586ed9c8e3d5a0ce2909a97bb (diff) | |
download | cpython-6a9e80a93148b13e4d3bceaab5ea1804ab0e64d5.zip cpython-6a9e80a93148b13e4d3bceaab5ea1804ab0e64d5.tar.gz cpython-6a9e80a93148b13e4d3bceaab5ea1804ab0e64d5.tar.bz2 |
bpo-40313: speed up bytes.hex() (GH-19594)
Automerge-Triggered-By: @gpshead
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2020-04-20-23-58-35.bpo-40313.USVRW8.rst | 1 | ||||
-rw-r--r-- | Python/pystrhex.c | 61 |
2 files changed, 50 insertions, 12 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-04-20-23-58-35.bpo-40313.USVRW8.rst b/Misc/NEWS.d/next/Core and Builtins/2020-04-20-23-58-35.bpo-40313.USVRW8.rst new file mode 100644 index 0000000..52880ab --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-04-20-23-58-35.bpo-40313.USVRW8.rst @@ -0,0 +1 @@ +Improve the performance of bytes.hex().
\ No newline at end of file diff --git a/Python/pystrhex.c b/Python/pystrhex.c index 7e4fad3..b74e57a 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -82,22 +82,59 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, /* Hexlify */ Py_ssize_t i, j; - for (i=j=0; i < arglen; ++i) { - assert((j + 1) < resultlen); - unsigned char c; - c = (argbuf[i] >> 4) & 0x0f; - retbuf[j++] = Py_hexdigits[c]; - c = argbuf[i] & 0x0f; - retbuf[j++] = Py_hexdigits[c]; - if (bytes_per_sep_group && i < arglen - 1) { - Py_ssize_t anchor; - anchor = (bytes_per_sep_group > 0) ? (arglen - 1 - i) : (i + 1); - if (anchor % abs_bytes_per_sep == 0) { + unsigned char c; + + if (bytes_per_sep_group == 0) { + for (i = j = 0; i < arglen; ++i) { + assert((j + 1) < resultlen); + c = argbuf[i]; + retbuf[j++] = Py_hexdigits[c >> 4]; + retbuf[j++] = Py_hexdigits[c & 0x0f]; + } + assert(j == resultlen); + } + else { + /* The number of complete chunk+sep periods */ + Py_ssize_t chunks = (arglen - 1) / abs_bytes_per_sep; + Py_ssize_t chunk; + unsigned int k; + + if (bytes_per_sep_group < 0) { + i = j = 0; + for (chunk = 0; chunk < chunks; chunk++) { + for (k = 0; k < abs_bytes_per_sep; k++) { + c = argbuf[i++]; + retbuf[j++] = Py_hexdigits[c >> 4]; + retbuf[j++] = Py_hexdigits[c & 0x0f]; + } retbuf[j++] = sep_char; } + while (i < arglen) { + c = argbuf[i++]; + retbuf[j++] = Py_hexdigits[c >> 4]; + retbuf[j++] = Py_hexdigits[c & 0x0f]; + } + assert(j == resultlen); + } + else { + i = arglen - 1; + j = resultlen - 1; + for (chunk = 0; chunk < chunks; chunk++) { + for (k = 0; k < abs_bytes_per_sep; k++) { + c = argbuf[i--]; + retbuf[j--] = Py_hexdigits[c & 0x0f]; + retbuf[j--] = Py_hexdigits[c >> 4]; + } + retbuf[j--] = sep_char; + } + while (i >= 0) { + c = argbuf[i--]; + retbuf[j--] = Py_hexdigits[c & 0x0f]; + retbuf[j--] = Py_hexdigits[c >> 4]; + } + assert(j == -1); } } - assert(j == resultlen); #ifdef Py_DEBUG if (!return_bytes) { |