perf: utilities_get_rgba_for_xy() allocates a GdkPixbuf per pixel read
- Dominant language
- Python
- Stars
- 869
- Forks
- 106
- PR merge metrics
- No merged PRs in 30d
Description
## Problem
`utilities_get_rgba_for_xy()` in `src/utilities/utilities_paths.py` calls `Gdk.pixbuf_get_from_surface(surface, x, y, 1, 1)` to read a single pixel. This allocates a full GdkPixbuf GObject on the heap for every call.
`utilities_get_magic_path()` (used by the paint bucket / magic wand) calls this function up to **50,000 times** per operation, making GObject allocation the dominant cost.
## Proposed Fix
Replace the GdkPixbuf allocation with a direct read from the Cairo surface pixel buffer via `surface.get_data()`, handling the BGRA→RGBA conversion and alpha un-premultiplication in Python.
Cache the buffer once in `utilities_get_magic_path()` instead of re-acquiring it per pixel.
## Measured Impact
Benchmarked on Python 3.12.3 / Cairo 1.18.0 / GTK 3 / Linux:
| Scenario | Before | After | Speedup |
|---|---|---|---|
| Single pixel read (median) | 3.5 μs | 0.78 μs | **4.5×** |
| 10,000 consecutive reads | 36.4 ms | 7.1 ms | **5.1×** |
| Paint bucket worst case (50K reads, projected) | ~180 ms | ~36 ms | **~5×** |
Also fixes an off-by-one in the bounds check (`x > width` → `x >= width`).
## Affected Tools
- Paint bucket / magic wand (heaviest user — 50K calls per fill)
- Color picker (per mouse-move)
- Eraser color comparison
Contributor guide
Research direction
Start in src/utilities/utilities_paths.py with utilities_get_rgba_for_xy() and utilities_get_magic_path(), then inspect how the Cairo surface exposes its pixel buffer. Replace the per-read GdkPixbuf allocation, reuse the buffer during magic-path processing, preserve BGRA/RGBA and alpha handling, and correct the bounds check; verify the measured pixel-read and fill performance.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- performance
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100