mimalloc issues

Shared Library On macOS Mojave

macOS Mojave version 10.14.5 
$ uname -a
Darwin Kernel Version 18.6.0

Add shared library (All of them works on Linux)

set (mi_sources
    src/stats.c
    src/os.c
    src/segment.c
    src/page.c
    src/alloc.c
    src/alloc-aligned.c
    src/heap.c
    src/options.c
    src/init.c)
.
.
.
add_library(mimalloc SHARED ${mi_sources})

test(failed)

$ ./dynamic-override 
[1]    72000 abort      ./dynamic-override

set (mi_sources SHARED
    src/stats.c
    src/os.c
    src/segment.c
    src/page.c
    src/alloc.c
    src/alloc-aligned.c
    src/heap.c
    src/options.c
    src/init.c)
.
.
.
add_library(mimalloc SHARED ${mi_sources})

test(success)

$ ./dynamic-override
heap stats:     peak      total      freed       unit      count  
   elapsed:     0.000 s
   process: user: 0.001 s, system: 0.001 s, faults: 0, reclaims: 405, rss: 848.0 kb

add_library(mimalloc SHARED     
    src/stats.c
    src/os.c
    src/segment.c
    src/page.c
    src/alloc.c
    src/alloc-aligned.c
    src/heap.c
    src/options.c
    src/init.c)

test(success)

$ ./dynamic-override
heap stats:     peak      total      freed       unit      count  
   elapsed:     0.000 s
   process: user: 0.001 s, system: 0.001 s, faults: 0, reclaims: 415, rss: 868.0 kb

Add header to usr/local/include (both on linux and macos) (done)

install(FILES include/mimalloc.h DESTINATION ${mi_install_dir}/include)

{$mi_install_dir} = lib/mimalloc-${mi_version}

but on guide

install the library and header files in /usr/local/lib and /usr/local/include

which lead to

$ gcc -o main -lmimalloc main.c 
main.c:3:10: fatal error: 'mimalloc.h' file not found
#include <mimalloc.h>
         ^~~~~~~~~~~~
1 error generated.

solution:

install(FILES include/mimalloc.h DESTINATION include)

#89

IRI build with Mimalloc

Full report

integrate with dltcollab iri (todo)

  • efficience comparison
  • updaet epic

Refactor page_queue

  • refactor mi_page_queue_remove to mi_page_queue_remove_clear
    • add _mi_page_queue_remove
    • add _mi_page_clear

_mi_page_queue_remove

static void _mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) {
  if (page->prev != NULL) page->prev->next = page->next;
  if (page->next != NULL) page->next->prev = page->prev;
  if (page == queue->last)  queue->last = page->prev;
  if (page == queue->first) {
    queue->first = page->next;
    // update first
    mi_heap_t* heap = page->heap;
    mi_assert_internal(mi_heap_contains_queue(heap, queue));
    mi_heap_queue_first_update(heap,queue);
  }
  page->heap->page_count--;
}

_mi_page_clear

static void _mi_page_clear(mi_page_t* page) {
  page->next = NULL;
  page->prev = NULL;
  page->heap = NULL;
  page->flags.in_full = false;
}

mi_page_queue_remove_clear

static void mi_page_queue_remove_clear(mi_page_queue_t* queue, mi_page_t* page) {
  mi_assert_internal(page != NULL);
  mi_assert_expensive(mi_page_queue_contains(queue, page));
  mi_assert_internal(page->block_size == queue->block_size || (page->block_size > MI_LARGE_SIZE_MAX && mi_page_queue_is_huge(queue))  || (page->flags.in_full && mi_page_queue_is_full(queue)));
  _mi_page_queue_remove(queue, page);
  _mi_page_clear(page);
}

  • refactor mi_page_queue_push
    • add _mi_page_queue_add
  • refactor mi_page_queue_enqueue_from
    • using _mi_page_queue_add _mi_page_queue_remove

_mi_page_queue_add

static void _mi_page_queue_add(mi_page_queue_t* queue,mi_page_t* page) {
  page->flags.in_full = mi_page_queue_is_full(queue);
  page->next = queue->first;
  page->prev = NULL;
  if (queue->first != NULL) {
    mi_assert_internal(queue->first->prev == NULL);
    queue->first->prev = page;
  }
  else {
    queue->last = page;
  }
  queue->first = page;
}

mi_page_queue_push

static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_t* page) {
  mi_assert_internal(page->heap == NULL);
  mi_assert_internal(!mi_page_queue_contains(queue, page));
  mi_assert_internal(page->block_size == queue->block_size || (page->block_size > MI_LARGE_SIZE_MAX && mi_page_queue_is_huge(queue)) || (page->flags.in_full && mi_page_queue_is_full(queue)));

  page->heap = heap;
  heap->page_count++;

  _mi_page_queue_add(queue, page);
  // update direct
  mi_heap_queue_first_update(heap, queue);
  
}

mi_page_queue_enqueue_from

static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) {
  mi_assert_internal(page != NULL);
  mi_assert_expensive(mi_page_queue_contains(from, page));
  mi_assert_expensive(!mi_page_queue_contains(to, page));
  mi_assert_internal(page->block_size == to->block_size ||
                     (page->block_size > MI_LARGE_SIZE_MAX && (mi_page_queue_is_huge(to) || mi_page_queue_is_full(to))) ||
                      (page->block_size == from->block_size && mi_page_queue_is_full(to)));

  _mi_page_queue_remove(from, page);
  mi_page_queue_push(page->heap, to, page);
}

Breaking long assertion lines

todo

  • add internal functions to internal function header file
    for instance mimalloc-internal.h
// "page.c"
void*      _mi_malloc_generic(mi_heap_t* heap, size_t size)  mi_attr_noexcept mi_attr_malloc;

void       _mi_page_retire(mi_page_t* page);                                  // free the page if there are no other pages with many free blocks
void       _mi_page_unfull(mi_page_t* page);
void       _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force);   // free the page
void       _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq);            // abandon the page, to be picked up by another thread...
void       _mi_heap_delayed_free(mi_heap_t* heap);

void       _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay);
size_t     _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append);
void       _mi_deferred_free(mi_heap_t* heap, bool force);

void       _mi_page_free_collect(mi_page_t* page);
void       _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page);   // callback from segments

size_t     _mi_bin_size(uint8_t bin);           // for stats
uint8_t    _mi_bin(size_t size);                // for stats
uint8_t    _mi_bsr(uintptr_t x);                // bit-scan-right, used on BSD in "os.c"
  • rename queue

reference

linux kernel list.h
linux kernel coding style

tags: Cprogramming
Select a repo