Repository navigation
Conversation
|
Oh, and for proof, with this reproducer gist: and |
Merging this PR will improve performance by ×2.93 warnings
Performance Changes
Tip Curious why performance improved? Comment Comparing Footnotes
|
This comment was marked as outdated.
This comment was marked as outdated.
| Py_ssize_t bufsize = row * state->ysize; | ||
| // Cap the size to the whole number of rows that fits an `int`. | ||
| // TODO: this needs to be changed when encoders' buffer sizes become `ssize_t`, | ||
| // like decoders did in ca1cf5925. |
There was a problem hiding this comment.
This isn't referring to an existing PR, right? You're presuming it will happen?
There was a problem hiding this comment.
No existing PR, it's just a note for a future implementer, be that me or someone else 😅
de42638 to
8703bf5
Compare
31a2c8d to
4fb5c27
Compare
|
I'd like the first attempt of this to be a PR to #9938 instead, just to avoid multiple PRs here about the same thing. It would be nicer if the community could agree on a solution to be reviewed, rather than having two competing PRs to be reviewed. If a PR to that fork goes unanswered for a time, then we can consider something else. |
|
A PR to what, sorry? |
|
Oh, sorry, wrong link. #9220 |
|
Yeah, this is basically a rebased rework of that year-old rebase-requiring PR that takes care of my comment (that went unanswered by the community) that the bufsize should only be grown for the raw encoder, in a generic way that lets an encoder tell the machinery about its optimal bufsize rather than the machinery needing to know about specifics. I'd say this PR should remain open if the other one may, too... |
|
@hugovk when merging please add this to the squash commit message so @lgeiger is credited for #9220: Co-authored-by: Lukas Geiger 13285808+lgeiger@users.noreply.github.com |
|
@aclark4life Thanks! ❤️ I rebased for cleanliness and added @lgeiger's Co-authored-by to b1bbc1d too. |
|
Great! thanks for pushing this over the finishing line |
Based on the computation in python-pillow#9220 Co-authored-by: Lukas Geiger <13285808+lgeiger@users.noreply.github.com>
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
|
@aclark4life Thanks, rebased, and adjusted the changelog :) |
| // Before the first `encode()` call, `bytes` is the packed row size, and `count` | ||
| // is the stride (or zero). After the first call, the two get swapped... | ||
| // The larger is the row size. | ||
| Py_ssize_t row = MAX(state->bytes, state->count); |
There was a problem hiding this comment.
This is only ever used in Image.py, before the call to encode(), so couldn't you just always use state->bytes?
There was a problem hiding this comment.
I could, but then I'd want to document that the value returned here is correct only before calling encode(), which sounds worse?
There was a problem hiding this comment.
...how about if the values weren't swapped after the first call? I've pushed a commit.
|
I've pushed some commits. The most significant of which is that |
|
@radarhere Thanks! Yeah, ImageFile wasn't actually in the scope of this PR (hence this PR's title) since it wasn't in the scope of the original #9220 either 😄 The title of the PR, as well as changelogs, might need to be updated now that this is no longer only about |
tobytes()|
It seemed weird to talk about adding an extra property to the encoders… but not actually use it for the most common encoding operation? Hopefully things are looking good now. I've updated the title. Feel free to update the release notes. |
I think we might actually not want to use this for |
I've created #10424 with the first commit. I don't know what you were trying to say with the second commit, because that's changing a test file that this PR adds.
Lines 681 to 684 in 56f0ece
|
|
Re c58a8c8: sorry, had a brain-frazzled-fart, unrelated.
They're two different comments according to annotate. The FIXME is effbot's, from 2006 or before. Not sure what it refers to -- For the rest, by my reading libjpeg apparently (sometimes) requires a single buffer large enough to store the entire encoded image, and that comment was added originally in 2013 by @wiredfool in 2a743c9 when that became a thing. The JPEG encoder could be changed to use But for the general case, by and large encoders are happy to work with smaller buffers.
Yep, I'm aware, and that gets even worse 😅... I measured locally, and on this branch (with Users can, as before, tweak
Me too.
Only the encoder knows the optimal bufsize (
That's up for discussion. If you'd rather it wasn't mentioned explicitly, I'll adjust.
I think it does belong there, so the protocol of it existing is explicit and available. I hope all third-party Python-implemented encoders extend from |
Closes #9220 (supersedes it).
This is an extension of my comment on #9220 (comment):
optimal_bufsizeproperty, the number of bytes needed in a byte buffer to encompass the whole encoding.Image.tobytes()now checks the optimal bufsize after it initializes the encoder, and passes it through if known; otherwise, the same old logic (the larger ofMAXBLOCK, or the memory required to encode a single 8-bit RGBA row) is used.tobytes()is being used in surprising places around Pillow (see the changelog fragment), so this should have pleasant effects all around...