- parallel: the error path waits only on futures it could not cancel, so a
pool shutdown that cancelled queued items (or ExitRequested in the inline
fallback) no longer hangs exit (#582)
- send: Send to All keeps the node-identity part of the revision after the
first write and relaxes only the graph version, so a workflow loaded
between sends is refused (#578)
- send: every node of Send to All takes a fresh ticket, so a window with
more than 100 nodes no longer refuses node 1 (#578)
- quality: close test file handles, drop unused locals, replace the
looked-up flag with a sentinel, single unittest.mock import, document the
BaseException re-raise and the startup banner print
* perf(images): read PNG text without decoding pixels (#523)
Pillow's PngImageFile.text loads every pixel to reach text chunks written
after IDAT. The scan's metadata batch and the image monitor now read PNG
text through utils/png_text.py, which runs Pillow's own chunk handlers
after the first IDAT and seeks over the pixel data.
The legacy .text read is the floor: a differential test compares both
readers on every fixture image, a curated corpus and a seeded fuzz. The
only difference is a file whose pixel data is undecodable or cut short:
it now keeps the text read before its pixels instead of reading nothing.
Animated PNGs still use .text.
* test(images): cover the text budget, XMP and layout guard of the PNG text walk (#523)
* perf(images): run image work on two own pools and trim after jobs (#523)
Image work no longer spreads over the default executor's threads, where
glibc kept an image-sized malloc arena per thread.
- Interactive image work (view previews behind their gate, workspace card
facts, both inspector routes) runs on the API's fixed pm-image pool of
3 threads; the on-demand preview pool is merged into it.
- map_parallel (scan metadata, thumbnail and convert jobs, the legacy
gallery generation, capture previews) shares one long-lived pm-worker
pool of Worker threads, reused between jobs. The package teardown stops
it within its bound (part "workers").
- After a scan, thumbnail or convert job, glibc's malloc_trim(0) returns
free pages once; a no-op on Windows, macOS and musl.
- tools/perf/memory_drive.py measures RSS, heap, threads and arenas under
the #523 load on the disposable browser test server (manual only).
* fix(images): start no image thread after the teardown; join retired job pools (#523)