Skip to content

Cap malloc arenas so extraction jobs fit their memory limit - #288

Merged
nonprofittechy merged 1 commit into
mainfrom
fix/extraction-worker-memory
Oct 8, 2026
Merged

nonprofittechy merged 1 commit into
mainfrom
fix/extraction-worker-memory

Conversation

@nonprofittechy

Copy link
Copy Markdown
Member

Every document extraction job failed with MemoryError when the worker ran on a multi-core workstation, so uploads never got analyzed locally.

Each job runs in a child process under RLIMIT_AS (DOCUMENT_EXTRACTION_MEMORY_MB, 768 MB by default), which limits address space, not memory in use. glibc reserves a malloc arena of up to 64 MB per thread, up to eight per CPU core, so the same job's address space grows with the host's core count. Measured on an eight-core machine with the sample PDF:

memory in use (peak RSS) address space (peak) under 768 MB
before 251 MB 824 MB MemoryError while loading the form crosswalk
MALLOC_ARENA_MAX=2 251 MB 440 MB completes

The worker now sets MALLOC_ARENA_MAX=2 before spawning children, keeping an operator's own value if one is set. The limit itself is unchanged; Fly's worker has one CPU, so its arena ceiling was already low.

Validation: worker tests (including that a spawned child sees the setting, and that an existing value is kept), full Python suite in the pre-push hook, and the real process_document_extractions --once completing a queued job under the default limit.

🤖 Generated with Claude Code

Each extraction child runs under RLIMIT_AS, which counts address space
rather than memory in use. glibc reserves a malloc arena of up to 64 MB
per thread, up to eight per CPU core, so the same job's address space
grows with the host's core count. On an eight-core workstation a job
that uses about 250 MB reached about 820 MB of address space, and every
job failed with MemoryError under the 768 MB default; on Fly's one-CPU
worker the ceiling is much lower.

Set MALLOC_ARENA_MAX=2 for the spawned children (an operator's own value
is kept). The same job then peaks at about 440 MB of address space and
completes under the default limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟢 Approval recommended

The focused change correctly addresses spawned-worker address-space overhead and includes appropriate regression coverage.

0 open findings

What changed in this PR

Caps glibc malloc arenas for spawned extraction workers to keep address-space usage within existing limits.

Changes:

  • Defaults MALLOC_ARENA_MAX to 2 while preserving operator overrides.
  • Tests default and preconfigured values.
File Description
efile_app/​efile/​management/​commands/​process_document_extractions.py Configures malloc arenas before spawning extraction jobs.
efile_app/​efile/​tests/​test_document_extractions.py Verifies default and overridden settings.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

@nonprofittechy
nonprofittechy merged commit f9f6cf9 into main Oct 8, 2026
9 checks passed
@nonprofittechy
nonprofittechy deleted the fix/extraction-worker-memory branch October 8, 2026 16:45
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.

2 participants