Skip to content

Improvements to heap-memory and PSRAM handling#4791

Merged
DedeHai merged 15 commits intowled:mainfrom
DedeHai:heap_handling
Sep 16, 2025
Merged

Improvements to heap-memory and PSRAM handling#4791
DedeHai merged 15 commits intowled:mainfrom
DedeHai:heap_handling

Conversation

@DedeHai
Copy link
Collaborator

@DedeHai DedeHai commented Jul 26, 2025

Besides better use of PSRAM and free heap handling in general there is a huge improvement for ESP32: with these changes it can work up to 64x64 pixels reliably without PSRAM (UI starts failing at half that size currently). Even got it to work up to about 80x64 pixels but UI access becomes unstable

  • Segment allocateData() uses more elaborate DRAM checking to reduce fragmentation and allow for larger setups to run on low heap
  • Segment allocateData() does not limit amount if PSRAM is available (put segment data in PSRAM if DRAM is depleted) -> prefer functionality over speed
  • Segment data allocation fails if minimum contiguous block size runs low to keep the UI working
  • Segment data allocation frees buffer if it is not small to not hog RAM excessively: if running a PS effect and then switching to something simpler, there is no need to keep a large buffer
  • Freeing large buffers in general instead of using realloc helps to defrag RAM as a large buffer can keep blocking contiguous RAM
  • Increased MAX_SEGMENT_DATA to account for better segment data handling
  • Memory allocation functions try to keep enough DRAM for segment data: if PSRAM is available, putting buffers in PSRAM has little impact on FPS (I saw 2% max drop in my tests) but putting effect data in PSRAM has a larger impact
  • Added constant PSRAM_THRESHOLD to improve PSARM usage: anything smaller is kept in DRAM, anything larger is put in PSRAM depending on how much heap is available. If heap is plenty, no PSRAM is used
  • ESP32 makes use of IRAM (no 8bit access) for pixeluffers, freeing about ~35k of heap
  • Global pixel buffer _pixels is always put in PSRAM if available (except if it fits in ESP32's 32bit IRAM)
  • Increase MIN_HEAP_SIZE to reduce risk of breaking UI due to low memory for JSON response (does not fix it entirely but ist a bit more stable)
  • Fix to properly get available heap on all platforms: added function getFreeHeapSize() and getContiguousFreeHeap()
  • Bugfix for effects that divide by SEGLEN: don't run FX in service() if segment is not active
  • Syntax fix in AR: calloc() uses (numelements, size) as arguments

the code may need some polishing (add debug outputs) and some fine-tuning of parameters as I did only test for borderline large 2D setups to see how well it performs under memory starvation but tested on all platforms.
There is a significant improvement if a board has PSRAM: there is virtually no limit to effect data and the heap is kept healthy and it is very stable, even with 10 overlapping segments of 32x32 pixels each.

Summary by CodeRabbit

  • New Features

    • Optional PSRAM-backed JSON and unified buffer allocator; enhanced memory diagnostics and runtime heap/contiguous-heap introspection.
  • Bug Fixes

    • Fixed audio-reactive FFT buffer allocation to prevent undersized allocations.
  • Refactor

    • Major memory-allocation overhaul: DRAM/PSRAM selection, PSRAM-preferred pixel/segment buffers, safer allocate/free paths and improved error handling to reduce fragmentation.
  • Chores

    • Platform memory thresholds, per-request heap controls and minor LED memory accounting updated.

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

Labels

Awaiting testing awesome enhancement optimization re-working an existing feature to be faster, or use less memory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants