-
Notifications
You must be signed in to change notification settings - Fork 708
User defined memory allocator for different purposes #3316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
User defined memory allocator for different purposes #3316
Conversation
which could know the memory's usage is for linear memory or not
use realloc_func to enlarge memory
move the CONFIG_WAMR_MEM_ALLOC_WITH_USAGE in nuttx
clang format the code
…g28849455/wasm-micro-runtime into feature/user_classified_mem_mng
@dongsheng28849455 the code adds control for the behavior of both wasm_runtime_malloc and wasm_memory_enlarge, but they are not so relevant, using a flag to control them may make the source code a little strange. I guess in your application the os_mmap uses the same allocator as the allocator of wasm_runtime_malloc, but it seems you just want to control the allocation of linear memory, so is it better to redirect os_mmap to use other allocator? Or add a flag for os_mmap? |
hi, @wenyongh, In our current application scenario, we hope to further customize memory allocators, distinguishing between linear memory and regular runtime managed memory. Compared to os_mmp with more abstraction, a customized memory allocator seems more suitable for this user specific usage scenario. |
build-scripts/config_common.cmake
Outdated
@@ -554,3 +554,6 @@ else () | |||
# Disable aot intrinsics for interp, fast-jit and llvm-jit | |||
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0) | |||
endif () | |||
if (WAMR_BUILD_MEM_ALLOC_WITH_USAGE EQUAL 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already a cmake variable WAMR_BUILD_ALLOC_WITH_USER_DATA
, here how about using WAMR_BUILD_ALLOC_WITH_USAGE
and putting these lines together with WAMR_BUILD_ALLOC_WITH_USER_DATA
?
And it seems only non shared memory is supported since the full_size_mmaped
isn't handled in wasm_enlarge_memory_internal, how about adding a check here, e.g. report error if WAMR_BUILD_SHARED_MEMORY
is defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already a cmake variable
WAMR_BUILD_ALLOC_WITH_USER_DATA
, here how about usingWAMR_BUILD_ALLOC_WITH_USAGE
and putting these lines together withWAMR_BUILD_ALLOC_WITH_USER_DATA
?
I'd like reuse WAMR_BUILD_ALLOC_WITH_USAGE, but that seems will change the API signiture of:
static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
that will impact its user.
BTW, the user defined malloc_func, realloc_func and free_func seems only have a hidden convention with its user, can we make it more abstract and explicitly declared in wamr_export.h? then we can include all of these things in general API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding WAMR_BUILD_ALLOC_WITH_USAGE is good (together with WAMR_BUILD_ALLOC_WITH_USER_DATA) to me, but since developer can just use wasm_export.h and libvmlib.a or libiwasm.so for his project, normally we should not add macro control in wasm_export.h, it is not easy to declare function prototypes for malloc_func/free_func, how about we just add comments about the prototypes in:
wasm-micro-runtime/core/iwasm/include/wasm_export.h
Lines 123 to 125 in 42199f1
void *malloc_func; | |
void *realloc_func; | |
void *free_func; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And if that, we had better update build_wamr.doc about the two cmake flags, and control the code like:
static void *(*malloc_func)(
#if WASM_MEM_ALLOC_WITH_USAGE
mem_alloc_usage_t usage,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA
void *user_data,
#endif
unsigned int size) = NULL;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about this in wamr_export.h:
typedef enum {
Alloc_For_Runtime,
Alloc_For_LinearMemory
} mem_alloc_usage_t;
typedef struct {
mem_alloc_usage_t usage;
void *user_data;
} user_data_t;
typedef void* (*malloc_func_t)(const user_data_t *data, uint64_t size);
typedef void* (*realloc_func_t)(const user_data_t *data, void *ptr, uint64_t size);
typedef void* (*free_func_t)(const user_data_t *data, void *ptr);
and in wasm_memory.c
static void *allocator_user_data = NULL;
static malloc_func_t malloc_func = NULL;
static realloc_func_t realloc_func = NULL;
static free_func_t free_func = NULL;
...
static bool
wasm_memory_init_with_allocator(malloc_func_t malloc_func_ptr, realloc_func_t realloc_func_ptr,
free_func_t free_func_ptr)
{
if (malloc_func_ptr && free_func_ptr && malloc_func_ptr != free_func_ptr) {
memory_mode = MEMORY_MODE_ALLOCATOR;
malloc_func = malloc_func_ptr;
realloc_func = realloc_func_ptr;
free_func = free_func_ptr;
return true;
}
LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n",
malloc_func_ptr, realloc_func_ptr, free_func_ptr);
return false;
}
then we can merge WASM_MEM_ALLOC_WITH_USAGE&WASM_MEM_ALLOC_WITH_USER_DATA together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference is we had better not change the signature of malloc_func/realloc_func functions for general scenarios, they have been used by many developers, changing them will cause many inconvenient.
ret = false; | ||
goto return_func; | ||
} | ||
memory->heap_data = memory_data_new + (heap_data_old - memory_data_old); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The heap data (base address) may be changed, should call mem_allocator_migrate
for it like below code since the internal pointers (absolute addresses) inside the heap should be updated, or they will point to invalid buffer. If not, allocation by wasm app or module_malloc by host may fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
if (CONFIG_INTERPRETERS_WAMR_MEM_ALLOC_WITH_USAGE) | ||
set(WAMR_BUILD_MEM_ALLOC_WITH_USAGE 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about CONFIG_INTERPRETERS_WAMR_ALLOC_WITH_USAGE
and WAMR_BUILD_ALLOC_WITH_USAGE
?
OK, a concern is that the aot code and some aot data sections are also allocated by os_mmap, will they cause memory fragmentation? |
The feature's purpose is not to eliminate the memory fragmentation, it's focus on processing linear memory separately from system normal heap. so as reduce the probability of being unable to allocate in the pool when fragmentation exists. |
OK, thanks. |
1, WAMR_BUILD_MEM_ALLOC_WITH_USAGE -> WAMR_BUILD_ALLOC_WITH_USAGE 2, redefine the malloc, free, realloc signature. 3, let customer handle full_size_mmaped also in its realloc. 4, update the doc
if (!(memory_data_new = | ||
realloc_func(Alloc_For_LinearMemory, full_size_mmaped, | ||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 | ||
NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had better use allocator_user_data
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when we handling the linear memory, this paremter is not used here, NULL just for passing build
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, thanks.
(void)map_size; | ||
free_func(Alloc_For_LinearMemory, | ||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 | ||
NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
if (!(memory_data_new = | ||
realloc_func(Alloc_For_LinearMemory, full_size_mmaped, | ||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 | ||
NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@dongsheng28849455 Could add essential document to docs instead leave them in commit message? It's not easy for end user to fetch these informations. |
good point, I have added some info in the doc: |
…e#3316) Some issues are related with memory fragmentation, which may cause the linear memory cannot be allocated. In WAMR, the memory managed by the system is often trivial, but linear memory usually directly allocates a large block and often remains unchanged for a long time. Their sensitivity and contribution to fragmentation are different, which is suitable for different allocation strategies. If we can control the linear memory's allocation, do not make it from system heap, the overhead of heap management might be avoided. Add `mem_alloc_usage_t usage` as the first argument for user defined malloc/realloc/free functions when `WAMR_BUILD_ALLOC_WITH_USAGE` cmake variable is set as 1, and make passing `Alloc_For_LinearMemory` to the argument when allocating the linear memory.
…e#3316) Some issues are related with memory fragmentation, which may cause the linear memory cannot be allocated. In WAMR, the memory managed by the system is often trivial, but linear memory usually directly allocates a large block and often remains unchanged for a long time. Their sensitivity and contribution to fragmentation are different, which is suitable for different allocation strategies. If we can control the linear memory's allocation, do not make it from system heap, the overhead of heap management might be avoided. Add `mem_alloc_usage_t usage` as the first argument for user defined malloc/realloc/free functions when `WAMR_BUILD_ALLOC_WITH_USAGE` cmake variable is set as 1, and make passing `Alloc_For_LinearMemory` to the argument when allocating the linear memory. Signed-off-by: victoryang00 <[email protected]>
…e#3316) Some issues are related with memory fragmentation, which may cause the linear memory cannot be allocated. In WAMR, the memory managed by the system is often trivial, but linear memory usually directly allocates a large block and often remains unchanged for a long time. Their sensitivity and contribution to fragmentation are different, which is suitable for different allocation strategies. If we can control the linear memory's allocation, do not make it from system heap, the overhead of heap management might be avoided. Add `mem_alloc_usage_t usage` as the first argument for user defined malloc/realloc/free functions when `WAMR_BUILD_ALLOC_WITH_USAGE` cmake variable is set as 1, and make passing `Alloc_For_LinearMemory` to the argument when allocating the linear memory.
…e#3316) Some issues are related with memory fragmentation, which may cause the linear memory cannot be allocated. In WAMR, the memory managed by the system is often trivial, but linear memory usually directly allocates a large block and often remains unchanged for a long time. Their sensitivity and contribution to fragmentation are different, which is suitable for different allocation strategies. If we can control the linear memory's allocation, do not make it from system heap, the overhead of heap management might be avoided. Add `mem_alloc_usage_t usage` as the first argument for user defined malloc/realloc/free functions when `WAMR_BUILD_ALLOC_WITH_USAGE` cmake variable is set as 1, and make passing `Alloc_For_LinearMemory` to the argument when allocating the linear memory. Signed-off-by: victoryang00 <[email protected]>
Some issues that related with memory fragmentation, which may cause the linear memory cannot be allocated. In WAMR, the memory managed by the system is often trivial, but linear memory usually directly allocates a large block and often remains unchanged for a long time. Their sensitivity and contribution to fragmentation are different, which is suitable for different allocation strategies. if we can control the linear memory's allocation, do not make it from system heap, the overhead of heap management might be avoided.