GeezerVison is showing github.com — [WIP] gh-129813: Add PyBytesWriter C API by vstinner · Pull Request #129814 · python/cpython
Conversation
vstinner
commented
Feb 7, 2025
•
edited by bedevere-app
Bot
Loading
Uh oh!
There was an error while loading. Please reload this page.
- Replace usage of the old private _PyBytesWriter with the new public PyBytesWriter C API.
- Remove the old private _PyBytesWriter C API.
- Add a freelist for PyBytesWriter_Create().
- TODO: write doc
- TODO: document new functions in What's New and Changelog
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
* Replace usage of the old private _PyBytesWriter with the new public
PyBytesWriter C API.
* Remove the old private _PyBytesWriter C API.
* Add a freelist for PyBytesWriter_Create().
* TODO: write doc
* TODO: document new functions in What's New and Changelog
|
The PR is big because it also replaces usage of the old private API with new public API. If the API is approved, I will split the PR into smaller pieces and measure the performance impact of these changes.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Some functions should be optimized after the removal of the private min_size member:
- unicode_encode_ucs1()
- utf8_encoder()
- PyBytes_FromFormatV()
These functions allocate a little bit too much memory, extend argument of PyBytesWriter_Extend() should be adjusted.
I just tried to make the code work, not to optimize it.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
This change has no impact on performance, even if the new public API allocates memory on the heap, instead of allocating on the stack. It uses a freelist to optimize PyBytesWriter_Create().
Example of microbenchmark on 3 functions:
import pyperf
import binascii
runner = pyperf.Runner()
runner.bench_func('from list 100', bytes, list(b'x' * 100))
runner.bench_func('from list 1,000', bytes, list(b'x' * 1_000))
runner.bench_func('from hex 100', bytes.fromhex, bytes(range(100)).hex())
runner.bench_func('from hex 1,000', bytes.fromhex, (b'x' * 1_000).hex())
runner.bench_func('b2a_uu', binascii.b2a_uu, b'x' * 45)
Result:
| Benchmark |
ref |
public |
| from list 100 |
672 ns |
647 ns: 1.04x faster |
| from list 1,000 |
6.22 us |
6.12 us: 1.02x faster |
| from hex 100 |
143 ns |
145 ns: 1.02x slower |
| from hex 1,000 |
1.02 us |
1.03 us: 1.00x slower |
| Geometric mean |
(ref) |
1.01x faster |
Benchmark hidden because not significant (1): b2a_uu
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
pseudo-tangential idea: Could this instead just be a C wrapper for io.BytesIO? Working to try to get to one fast implementation to read/write a bytes object.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
pseudo-tangential idea: Could this instead just be a C wrapper for io.BytesIO?
io.BytesIO API is basically the write(bytes) method, whereas proposed PyBytesWriter API gives directly a pointer into a buffer. It's a different API. I don't think that io.BytesIO API can or should be modified to give directly a pointer. io.BytesIO is more complex since it allows changing the position, the seek() method, and also reading, the read() method.
|
cmaloney reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Reviewers
ericsnowcurrently
Awaiting requested review from ericsnowcurrently
ericsnowcurrently will be requested when the pull request is marked ready for review
ericsnowcurrently is a code owner
ZeroIntensity
Awaiting requested review from ZeroIntensity
ZeroIntensity will be requested when the pull request is marked ready for review
ZeroIntensity is a code owner
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|