How to Configure the MULLE_ALLOCA_STACKSIZE Threshold in mulle-allocator
MULLE_ALLOCA_STACKSIZE is a compile-time macro that sets the boundary (default 128 bytes) between stack allocation via alloca() and heap allocation via mulle_malloc in the mulle-allocator library.
The mulle-allocator repository provides a flexible temporary memory allocation system that automatically chooses between the stack and heap based on request size. Understanding how to tune the MULLE_ALLOCA_STACKSIZE threshold allows you to optimize performance for embedded constraints or high-throughput data processing. This guide covers the implementation details in src/mulle-alloca.h and the practical methods for customizing this value in the mulle-c/mulle-allocator codebase.
Default Value and Source Definition
The default threshold is defined in src/mulle-alloca.h at lines 108–109:
#ifndef MULLE_ALLOCA_STACKSIZE
# define MULLE_ALLOCA_STACKSIZE 128 // bytes, equivalent of double[16]
#endif
This 128-byte default represents the size of sixteen double values. When mulle_alloca_do requests memory, the library compares the requested size against this constant to determine the allocation strategy.
Why Adjust the Stack Size Threshold
You should consider modifying MULLE_ALLOCA_STACKSIZE when your target environment has specific memory constraints or performance requirements:
- Embedded systems with limited stack space – The default 128 bytes may exceed available stack memory, risking overflow crashes in deeply nested call chains.
- High-volume data processing – Increasing the threshold allows larger temporary buffers to reside on the stack, eliminating heap allocation overhead and cache misses.
- Nested allocation scenarios – When multiple
mulle_alloca_doblocks exist in the same call chain, each allocation consumes stack space; the effective safe limit per level is effectively halved with each nesting level.
Three Methods to Configure MULLE_ALLOCA_STACKSIZE
All configuration methods must execute before mulle-alloca.h is included. The macro uses #ifndef guards, so the first definition encountered takes precedence.
Compiler Flag (Recommended)
Define the macro on the compiler command line to ensure consistency across all translation units:
gcc -DMULLE_ALLOCA_STACKSIZE=256 -o myprog myprog.c
With CMake and mulle-sde:
mulle-sde add -D"MULLE_ALLOCA_STACKSIZE=256"
Or using target_compile_definitions in CMakeLists.txt:
add_executable(myapp main.c)
target_compile_definitions(myapp PRIVATE MULLE_ALLOCA_STACKSIZE=1024)
target_link_libraries(myapp PRIVATE mulle-allocator)
Project-Wide Header
Add the definition to a central project header that all source files include before mulle-alloca.h:
/* config.h */
#define MULLE_ALLOCA_STACKSIZE 256
/* All other headers */
#include "mulle-alloca.h"
File-Local Override
For targeted optimization of specific modules, define the macro immediately before the include statement:
#define MULLE_ALLOCA_STACKSIZE 512 // increase to 512 B for this file only
#include "mulle-alloca.h"
void process(char *input)
{
mulle_alloca_do(buf, char, strlen(input) + 1)
{
strcpy(buf, input);
printf("%s\n", buf);
}
}
How the Threshold Affects Allocation Logic
The decision logic resides in src/mulle-alloca.h around line 281. When mulle_alloca_do expands:
- If
size <= MULLE_ALLOCA_STACKSIZE, the macro allocates an automatic array on the stack usingalloca(). - If
size > MULLE_ALLOCA_STACKSIZE, the macro allocates memory on the heap usingmulle_malloc()and automatically frees it when the scope exits.
This transparent fallback ensures that large allocations never risk stack overflow while small allocations maintain maximum performance.
Verifying Your Configuration
Confirm the effective value at compile time by printing it from your source:
#include <stdio.h>
#define MULLE_ALLOCA_STACKSIZE 256 // test value
#include "mulle-alloca.h"
int main(void)
{
printf("MULLE_ALLOCA_STACKSIZE = %d\n", MULLE_ALLOCA_STACKSIZE);
return 0;
}
Compile and run; the output must match your intended value. If it displays 128, your definition occurred after the header inclusion or was overridden by a previous definition.
Code Examples
Global Configuration in CMake
cmake_minimum_required(VERSION 3.10)
project(MyProject)
add_executable(myapp src/main.c src/fast_path.c)
target_compile_definitions(myapp PRIVATE MULLE_ALLOCA_STACKSIZE=1024)
target_link_libraries(myapp PRIVATE mulle-allocator)
Per-File Optimization for Critical Paths
/* fast_path.c */
#define MULLE_ALLOCA_STACKSIZE 256
#include "mulle-alloca.h"
void fast_path(const char *src)
{
size_t len = strlen(src) + 1;
mulle_alloca_do(buf, char, len)
{
memcpy(buf, src, len);
/* processing with guaranteed stack allocation */
}
}
Runtime Flexibility with mulle_alloca_do_flexible
When you need different thresholds per invocation without recompiling, use the flexible variant defined near line 495 in src/mulle-alloca.h:
#define MULLE_ALLOCA_STACKSIZE 128 // default fallback
#include "mulle-alloca.h"
void variable_size(const char *s, size_t desired_stack)
{
mulle_alloca_do_flexible(buf, char, strlen(s) + 1, desired_stack)
{
strcpy(buf, s);
puts(buf);
}
}
This macro accepts a runtime desired_stack parameter that overrides the compile-time default for that specific allocation.
Summary
- MULLE_ALLOCA_STACKSIZE defaults to 128 bytes (16 doubles) and is defined in
src/mulle-alloca.h. - The threshold determines whether
mulle_alloca_douses stack allocation (alloca()) or heap allocation (mulle_malloc()). - Override the default via compiler flags (
-DMULLE_ALLOCA_STACKSIZE=N), project headers, or file-local definitions placed before the include. - For per-call flexibility without recompilation, use
mulle_alloca_do_flexibleto specify thresholds at runtime. - Always verify your setting with a test print statement to ensure the definition precedence worked correctly.
Frequently Asked Questions
What is the default MULLE_ALLOCA_STACKSIZE value?
The default value is 128 bytes, equivalent to the size of double[16]. This is defined in src/mulle-alloca.h lines 108–109 within an #ifndef guard, allowing compile-time overrides.
When should I decrease MULLE_ALLOCA_STACKSIZE?
Decrease the threshold when targeting very small embedded systems with limited stack space, or when your application uses deeply nested mulle_alloca_do blocks. Each nesting level consumes additional stack space, effectively halving the safe allocation size per level according to the repository documentation.
Can I set different thresholds for different function calls?
Yes. While MULLE_ALLOCA_STACKSIZE is a compile-time constant, you can use mulle_alloca_do_flexible (defined around line 495 in src/mulle-alloca.h) to pass a runtime stack-size limit per invocation. Alternatively, use file-local #define statements before including the header to vary thresholds between source files.
Does changing MULLE_ALLOCA_STACKSIZE affect binary compatibility?
No. MULLE_ALLOCA_STACKSIZE is a compile-time constant that affects only the expansion of mulle_alloca_do macros within your translation units. It does not change the ABI or layout of structures, though it will alter the stack usage characteristics of your compiled code. All translation units in a project should use the same value to ensure consistent behavior.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →