Skip to content

Fix: dynamic memory guard to prevent OOM on large queries#56

Merged
EVWorth merged 3 commits intomainfrom
fix/oom-large-tables
May 3, 2026
Merged

Fix: dynamic memory guard to prevent OOM on large queries#56
EVWorth merged 3 commits intomainfrom
fix/oom-large-tables

Conversation

@EVWorth
Copy link
Copy Markdown
Owner

@EVWorth EVWorth commented May 2, 2026

Problem

Loading large tables causes out-of-memory crashes. Query results flow through 3 memory copies: Rust Vec -> JSON IPC -> Zustand store -> useMemo object conversion. No streaming or pagination exists.

Solution

  • MemoryGuard monitors process RSS every 1000 rows during query fetch
  • Threshold at 75% of system RAM - adapts to whatever machine is running
  • Graceful stop when threshold hit: breaks stream, returns accumulated rows with warning
  • User LIMIT still respected - no forced limit injection when user doesn't specify one
  • Frontend warnings banner - displays backend warnings (e.g. memory guard trigger)

Changes

Rust (mas-core/query/executor.rs)

  • Added sysinfo crate for process memory monitoring
  • MemoryGuard struct: tracks RSS, triggers at 75% system RAM threshold
  • Checks every 1000 rows during fetch_many stream
  • On trigger: stops fetch, returns accumulated rows with warnings and rows_truncated: true
  • Removed hardcoded 50k row cap and forced LIMIT injection

Rust (mas-core/error.rs)

  • Added OutOfMemory(String) error variant

Frontend (ResultsGrid.tsx)

  • Render warnings[] array from backend results
  • Removed hardcoded "50,000" from truncation message

Testing

  • cargo check -p mas-core - compiles clean
  • All 275 frontend unit tests pass

Future Work

  • Proper pagination / fetch-more UI
  • Streaming result fetching architecture
  • SQLite-backed result caching for large datasets

Closes #25

- Always apply LIMIT to SELECT/SHOW/DESCRIBE/EXPLAIN (was conditional)
- Hard cap at 50,000 rows regardless of user settings
- Fix rows_truncated detection to compare against capped_limit
- Lower frontend virtualization threshold from 500 to 100 rows
- Add truncation warning banner when results are capped

Closes #25

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 2, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 30.15873% with 44 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src-tauri/crates/mas-core/src/query/executor.rs 32.20% 40 Missing ⚠️
src/components/grid/ResultsGrid.tsx 0.00% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

- Remove hardcoded 50k row cap
- Add sysinfo crate for process memory monitoring
- MemoryGuard checks RSS every 1000 rows during fetch
- Triggers when process hits 75% of system RAM
- Gracefully stops fetch and returns accumulated rows with warning
- Add OutOfMemory error variant to CoreError
- Update frontend to show backend warnings
- Truncation banner no longer mentions arbitrary 50k number
@EVWorth EVWorth changed the title Fix: enforce 50k row hard cap to prevent OOM on large queries Fix: dynamic memory guard to prevent OOM on large queries May 3, 2026
- Collapse nested if into single condition (clippy::collapsible_if)
- Use is_multiple_of(1000) instead of % 1000 == 0 (clippy::manual_is_multiple_of)
- Run cargo fmt for consistent formatting
@EVWorth EVWorth merged commit eb99303 into main May 3, 2026
5 checks passed
@EVWorth EVWorth deleted the fix/oom-large-tables branch May 3, 2026 14:50
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.

Loading large tables eats memory and causes an OOM error

2 participants