Title: gh-101178: Add Ascii85, Base85, and Z85 support to binascii by kangtastic · Pull Request #102753 · python/cpython · GitHub
Open Graph Title: gh-101178: Add Ascii85, Base85, and Z85 support to binascii by kangtastic · Pull Request #102753 · python/cpython
X Title: gh-101178: Add Ascii85, Base85, and Z85 support to binascii by kangtastic · Pull Request #102753 · python/cpython
Description: Synopsis Add Ascii85, Base85, and Z85 encoder and decoder functions implemented in C to binascii and use them to greatly improve the performance and reduce the memory usage of the existing Ascii85, Base85, and Z85 codec functions in base64. No API or documentation changes are necessary with respect to any functions in base64, and all existing unit tests for those functions continue to pass without modification. Resolves: gh-101178 Discussion The base85-related functions in base64 are now wrappers for the new functions in binascii, as envisioned in the docs: The binascii module contains a number of methods to convert between binary and various ASCII-encoded binary representations. Normally, you will not use these functions directly but use wrapper modules like uu or base64 instead. The binascii module contains low-level functions written in C for greater speed that are used by the higher-level modules. Parting out Ascii85 from Base85 and Z85 was warranted in my testing despite the code duplication due to the various performance-murdering special cases in Ascii85. Comments and questions are welcome. Benchmarks Updated December 28, 2025. # bench_b85.py # Note: EXTREMELY SLOW on unmodified mainline CPython # when tracing malloc on the base-85 functions. import base64 import sys import timeit import tracemalloc funcs = [(base64.b64encode, base64.b64decode), # sanity check/comparison (base64.a85encode, base64.a85decode), (base64.b85encode, base64.b85decode), (base64.z85encode, base64.z85decode)] def mb(n): return f"{n / 1024 / 1024:.3f} MB" def stats(func, data, t, m): name, n, bps = func.__qualname__, len(data), len(data) / t print(f"{name} : {n} b in {t:.3f} s ({mb(bps)}/s) using {mb(m)}") if __name__ == "__main__": data = b"a" * int(sys.argv[1]) * 1024 * 1024 for fenc, fdec in funcs: tracemalloc.start() enc = fenc(data) menc = tracemalloc.get_traced_memory()[1] - len(enc) tracemalloc.stop() tenc = timeit.timeit("fenc(data)", number=1, globals=globals()) stats(fenc, data, tenc, menc) tracemalloc.start() dec = fenc(enc) mdec = tracemalloc.get_traced_memory()[1] - len(dec) tracemalloc.stop() tdec = timeit.timeit("fdec(enc)", number=1, globals=globals()) stats(fdec, enc, tdec, mdec) # Python 3.15.0a3+ (heads/main:0efbad60e13, Dec 28 2025, 11:02:16) # ./configure --enable-optimizations --with-lto # Unmodified $ time ./python bench_b85.py 64 b64encode : 67108864 b in 0.092 s (693.266 MB/s) using 42.667 MB b64decode : 89478488 b in 0.234 s (364.961 MB/s) using 56.889 MB a85encode : 67108864 b in 7.163 s (8.935 MB/s) using 2664.401 MB a85decode : 83886080 b in 14.478 s (5.526 MB/s) using 3332.254 MB b85encode : 67108864 b in 6.965 s (9.189 MB/s) using 2664.401 MB b85decode : 83886080 b in 10.082 s (7.935 MB/s) using 3332.254 MB z85encode : 67108864 b in 7.245 s (8.834 MB/s) using 2664.102 MB z85decode : 83886080 b in 9.666 s (8.277 MB/s) using 3332.254 MB real 9m44.382s user 9m27.271s sys 0m12.747s # With this PR b64encode : 67108864 b in 0.085 s (753.375 MB/s) using 42.667 MB b64decode : 89478488 b in 0.230 s (371.282 MB/s) using 56.889 MB a85encode : 67108864 b in 0.094 s (681.709 MB/s) using 0.000 MB a85decode : 83886080 b in 0.191 s (418.019 MB/s) using 0.000 MB b85encode : 67108864 b in 0.075 s (850.118 MB/s) using 0.000 MB b85decode : 83886080 b in 0.141 s (567.490 MB/s) using 0.000 MB z85encode : 67108864 b in 0.074 s (864.559 MB/s) using 0.000 MB z85decode : 83886080 b in 0.173 s (462.854 MB/s) using 0.000 MB real 0m1.865s user 0m1.726s sys 0m0.126s The old pure-Python implementation is two orders of magnitude slower and uses over O(40n) temporary memory.
Open Graph Description: Synopsis Add Ascii85, Base85, and Z85 encoder and decoder functions implemented in C to binascii and use them to greatly improve the performance and reduce the memory usage of the existing Ascii85,...
X Description: Synopsis Add Ascii85, Base85, and Z85 encoder and decoder functions implemented in C to binascii and use them to greatly improve the performance and reduce the memory usage of the existing Ascii85,...
Opengraph URL: https://github.com/python/cpython/pull/102753
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/checks(.:format) |
| route-controller | pull_requests |
| route-action | checks |
| fetch-nonce | v2:f7014688-0382-1462-0e17-1cde38a48a2e |
| current-catalog-service-hash | 87dc3bc62d9b466312751bfd5f889726f4f1337bdff4e8be7da7c93d6c00a25a |
| request-id | CFDE:16E0FE:ABF9B:F0485:696A0CD1 |
| html-safe-nonce | b8dade41d68c87284e1fff204c7519734599a2f34979254d828ab70cd3891531 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDRkRFOjE2RTBGRTpBQkY5QjpGMDQ4NTo2OTZBMENEMSIsInZpc2l0b3JfaWQiOiI2OTAwMzQyMjUzOTE4MjI3NjY1IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | a1feb2136a407708790ed7cd5b4c41547c7e5f77372cb9f3990d4682d9933794 |
| hovercard-subject-tag | pull_request:1278422982 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,checks,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/python/cpython/pull/102753/checks |
| twitter:image | https://avatars.githubusercontent.com/u/942136?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/942136?s=400&v=4 |
| og:image:alt | Synopsis Add Ascii85, Base85, and Z85 encoder and decoder functions implemented in C to binascii and use them to greatly improve the performance and reduce the memory usage of the existing Ascii85,... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 699227a00bbb7fe1eec276d2ae1c3a93068bc5ba483bd9dc4b2a27a8f4f2f595 |
| turbo-cache-control | no-cache |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive full-width full-width-p-0 |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7266b2d935baa1c6474b16dd9feaa5ca30607261 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width