mm/tlsf:add mempool to optimize small block perfomance

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao 2022-11-07 21:55:13 +08:00 committed by Xiang Xiao
parent bdcb1f6a25
commit cb404167a7

View File

@ -38,6 +38,7 @@
#include <nuttx/fs/procfs.h> #include <nuttx/fs/procfs.h>
#include <nuttx/mutex.h> #include <nuttx/mutex.h>
#include <nuttx/mm/mm.h> #include <nuttx/mm/mm.h>
#include <nuttx/mm/mempool.h>
#include "tlsf/tlsf.h" #include "tlsf/tlsf.h"
#include "kasan/kasan.h" #include "kasan/kasan.h"
@ -52,6 +53,14 @@
# define MM_PTR_FMT_WIDTH 19 # define MM_PTR_FMT_WIDTH 19
#endif #endif
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
# define MM_MPOOL_BIT (1 << 0)
# define MM_IS_FROM_MEMPOOL(mem) \
((*((FAR size_t *)(mem) - 1)) & MM_MPOOL_BIT) == 0
#endif
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@ -84,6 +93,14 @@ struct mm_heap_s
tlsf_t mm_tlsf; /* The tlfs context */ tlsf_t mm_tlsf; /* The tlfs context */
/* The is a multiple mempool of the heap */
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
struct mempool_multiple_s mm_mpool;
struct mempool_s mm_pools[CONFIG_MM_HEAP_MEMPOOL_THRESHOLD /
sizeof(uintptr_t)];
#endif
/* Free delay list, for some situation can't do free immdiately */ /* Free delay list, for some situation can't do free immdiately */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
@ -617,6 +634,14 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
return; return;
} }
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
if (MM_IS_FROM_MEMPOOL(mem))
{
mempool_multiple_free(&heap->mm_mpool, mem);
return;
}
#endif
if (mm_lock(heap) == 0) if (mm_lock(heap) == 0)
{ {
kasan_poison(mem, mm_malloc_size(mem)); kasan_poison(mem, mm_malloc_size(mem));
@ -714,6 +739,9 @@ FAR struct mm_heap_s *mm_initialize(FAR const char *name,
FAR void *heapstart, size_t heapsize) FAR void *heapstart, size_t heapsize)
{ {
FAR struct mm_heap_s *heap; FAR struct mm_heap_s *heap;
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
int i;
#endif
minfo("Heap: name=%s start=%p size=%zu\n", name, heapstart, heapsize); minfo("Heap: name=%s start=%p size=%zu\n", name, heapstart, heapsize);
@ -725,6 +753,20 @@ FAR struct mm_heap_s *mm_initialize(FAR const char *name,
heapstart += sizeof(struct mm_heap_s); heapstart += sizeof(struct mm_heap_s);
heapsize -= sizeof(struct mm_heap_s); heapsize -= sizeof(struct mm_heap_s);
/* Initialize the multiple mempool in heap */
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
heap->mm_mpool.pools = heap->mm_pools;
heap->mm_mpool.npools = sizeof(heap->mm_pools) / sizeof(heap->mm_pools[0]);
for (i = 0; i < heap->mm_mpool.npools; i++)
{
heap->mm_pools[i].blocksize = (i + 1) * sizeof(uintptr_t);
heap->mm_pools[i].expandsize = CONFIG_MM_HEAP_MEMPOOL_EXPAND;
}
mempool_multiple_init(&heap->mm_mpool, name);
#endif
/* Allocate and create TLSF context */ /* Allocate and create TLSF context */
DEBUGASSERT(heapsize > tlsf_size()); DEBUGASSERT(heapsize > tlsf_size());
@ -887,6 +929,13 @@ void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid)
size_t mm_malloc_size(FAR void *mem) size_t mm_malloc_size(FAR void *mem)
{ {
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
if (MM_IS_FROM_MEMPOOL(mem))
{
return mempool_multiple_alloc_size(mem);
}
#endif
#if CONFIG_MM_BACKTRACE >= 0 #if CONFIG_MM_BACKTRACE >= 0
return tlsf_block_size(mem) - sizeof(struct memdump_backtrace_s); return tlsf_block_size(mem) - sizeof(struct memdump_backtrace_s);
#else #else
@ -909,6 +958,14 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
{ {
FAR void *ret; FAR void *ret;
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
ret = mempool_multiple_alloc(&heap->mm_mpool, size);
if (ret != NULL)
{
return ret;
}
#endif
/* Free the delay list first */ /* Free the delay list first */
free_delaylist(heap); free_delaylist(heap);
@ -956,6 +1013,14 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
{ {
FAR void *ret; FAR void *ret;
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
ret = mempool_multiple_memalign(&heap->mm_mpool, alignment, size);
if (ret != NULL)
{
return ret;
}
#endif
/* Free the delay list first */ /* Free the delay list first */
free_delaylist(heap); free_delaylist(heap);
@ -1012,7 +1077,6 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
{ {
FAR void *newmem; FAR void *newmem;
#ifdef CONFIG_MM_KASAN
if (oldmem == NULL) if (oldmem == NULL)
{ {
return mm_malloc(heap, size); return mm_malloc(heap, size);
@ -1024,6 +1088,38 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
return NULL; return NULL;
} }
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
if (MM_IS_FROM_MEMPOOL(oldmem))
{
newmem = mempool_multiple_realloc(&heap->mm_mpool, oldmem, size);
if (newmem != NULL)
{
return newmem;
}
newmem = mm_malloc(heap, size);
if (newmem != NULL)
{
memcpy(newmem, oldmem, size);
mempool_multiple_free(&heap->mm_mpool, oldmem);
}
return newmem;
}
else
{
newmem = mempool_multiple_alloc(&heap->mm_mpool, size);
if (newmem != NULL)
{
memcpy(newmem, oldmem, MIN(size, mm_malloc_size(oldmem)));
mm_free(heap, oldmem);
return newmem;
}
}
#endif
#ifdef CONFIG_MM_KASAN
newmem = mm_malloc(heap, size); newmem = mm_malloc(heap, size);
if (newmem) if (newmem)
{ {