Skip to content

perf: Free image buffers sooner during figure extraction - #4523

Draft
CyMule wants to merge 8 commits into
mainfrom
perf/bound-extracted-image-buffer-lifetimes
Draft

CyMule wants to merge 8 commits into
mainfrom
perf/bound-extracted-image-buffer-lifetimes

Conversation

@CyMule

@CyMule CyMule commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Image and PDF figure extraction now frees each decoded page, crop and JPEG buffer as soon as it is no longer needed. Image uploads are copied to the temporary file in 1 MiB blocks instead of being held in memory whole.

Extracting two full-page figures from a 100-megapixel image:

  • Peak memory: about 802 MiB lower (1,926,848 → 1,105,296 KiB).
  • Under a 1,200 MiB limit, main is OOM-killed and this branch completes.
  • Output is byte-identical.

What changed

  • Uploads are copied to the existing temporary file in 1 MiB blocks.
  • Decoded pages, RGBA intermediates, output crops and JPEG buffers are closed as soon as their pixels or bytes are used.

Behavior

  • Unchanged: JPEG bytes, Base64 payloads, saved filenames, element order, metadata and padding. Caller-owned streams keep the same rewind/EOF behavior.
  • No size cap or disk policy is added; image uploads already used the same temporary file.
  • Output payloads, and the current page plus its crop, can still be large.

Validation

  • 100 extraction/utility tests pass. They include:
    • exact JPEG bytes for RGB, RGBA and grayscale, in both payload and saved-file output;
    • bounded upload reads;
    • caller stream ownership and EOF;
    • multi-crop cleanup after an encoder failure.
  • The nine new regression tests also pass in an isolated Linux container against the module from this commit (import path and SHA256 verified).
  • Included benchmark: two full-page figures from a deterministic 100-megapixel image.
    • At a 1,200 MiB limit, main is OOM-killed (exit 137) and this branch completes.
    • A healthy main run produces the same metadata and payload hash.
    • At 3 GiB, peak RSS falls as above. Extraction takes 2.50 s on main and 2.33 s on this branch.
    • This measures the extraction stage, not end-to-end partition latency.
  • Full native PDF/image suite: 475 passed, 3 skipped. Ruff, diff checks and the version checker pass.

Release

Proposes 0.27.23, after #4419 (0.27.19), #4516 (0.27.20), #4517 (0.27.21) and #4357 (0.27.22). Renumber the version and changelog heading if that order changes, or if another PR takes 0.27.19 first.

#4516 also edits pdf_image_utils.py, but a different function. Downstream dependency bumps need the published release.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread scripts/performance/benchmark_image_extraction_memory.py
@CyMule CyMule changed the title perf: Bound extracted image buffer lifetimes perf: Free image buffers sooner during figure extraction Oct 5, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant