Skip to content

Speed up getpixel() and get_flattened_data() - #9881

Open
akx wants to merge 2 commits into
python-pillow:mainfrom
akx:fast-flat
Open

Speed up getpixel() and get_flattened_data()#9881
akx wants to merge 2 commits into
python-pillow:mainfrom
akx:fast-flat

Conversation

@akx

@akx akx commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Came up as a side-effect of #9292 + https://github.com/akx/Pillow/pull/13/changes#r3819140811. Doesn't change the memory price of get_flattened_data() though.

Locally (pay no heed to the benchmarks' commit IDs; this final version has less redundant mode tests and as such, different commits):

---------------------------- benchmark: 8 tests, 2 sources ----------------------------
Name (time in ms)                          0001_03fd7da Min  0002_e70ed66 Min      ΔMin
---------------------------------------------------------------------------------------
test_get_flattened_data[1237x811-I]                  6.8375            6.9130     +1.1%
test_get_flattened_data[1237x811-P]                  6.9563            6.9265     -0.4%
test_get_flattened_data[1237x811-L]                  7.0001            6.9799     -0.3%
test_get_flattened_data[1237x811-1]                  7.0226            6.9455     -1.1%
test_get_flattened_data[1237x811-F]                 15.2092           15.2749     +0.4%
test_get_flattened_data[1237x811-LA]                51.0383           38.8171    -23.9%
test_get_flattened_data[1237x811-RGB]               59.7311           43.9531    -26.4%
test_get_flattened_data[1237x811-RGBA]              66.1110           47.2317    -28.6%

Something that isn't necessarily captured by the benchmark is the PyObject_GC_UnTrack change; since we know that these tuples (immutable, as tuples are) will only contain 8-bit integers (and as an aside, CPython has likely returned cached small-integer references), we can tell the GC to not bother peeking inside them to see if there are cycles. This means that the next GC after get_flattened_data will not need to do that itself (it does need to do it for the tuple() cast from get_flattened_data once though).

akx added 2 commits August 20, 2026 11:35
* Build N-tuples by hand instead of Py_BuildValue parsing format strings over and over
* Tell the Python GC that the returned tuple contains no objects that may cause cycles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants