merge from dev-exp

This commit is contained in:
daan 2019-11-01 22:04:20 -07:00
commit 08c4726043
6 changed files with 91 additions and 37 deletions

View file

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.0)
project(libmimalloc C CXX)
include("cmake/mimalloc-config-version.cmake")
include("CheckIncludeFile")
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
@ -87,6 +89,16 @@ if(MI_USE_CXX MATCHES "ON")
set_source_files_properties(src/static.c test/test-api.c PROPERTIES LANGUAGE CXX )
endif()
CHECK_INCLUDE_FILE("numaif.h" MI_HAVE_NUMA_H)
if(MI_HAVE_NUMA_H)
list(APPEND mi_defines MI_HAS_NUMA)
list(APPEND mi_libraries numa)
else()
if (NOT(WIN32))
message(WARNING "Compiling without using NUMA optimized allocation (on Linux, install libnuma-dev?)")
endif()
endif()
# Compiler flags
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas)

View file

@ -57,7 +57,7 @@ void _mi_os_init(void); // called fro
void* _mi_os_alloc(size_t size, mi_stats_t* stats); // to allocate thread local data
void _mi_os_free(void* p, size_t size, mi_stats_t* stats); // to free thread local data
size_t _mi_os_good_alloc_size(size_t size);
int _mi_os_numa_node(void);
int _mi_os_numa_node(mi_os_tld_t* tld);
bool _mi_os_protect(void* addr, size_t size);
bool _mi_os_unprotect(void* addr, size_t size);

View file

@ -432,6 +432,7 @@ typedef struct mi_segments_tld_s {
// OS thread local data
typedef struct mi_os_tld_s {
size_t region_idx; // start point for next allocation
int numa_node; // numa node associated with this thread
mi_stats_t* stats; // points to tld stats
} mi_os_tld_t;

View file

@ -268,7 +268,7 @@ void* _mi_arena_alloc_aligned(size_t size, size_t alignment,
{
size_t asize = _mi_align_up(size, MI_ARENA_BLOCK_SIZE);
size_t bcount = asize / MI_ARENA_BLOCK_SIZE;
int numa_node = _mi_os_numa_node(); // current numa node
int numa_node = _mi_os_numa_node(tld); // current numa node
mi_assert_internal(size <= bcount*MI_ARENA_BLOCK_SIZE);
// try numa affine allocation

View file

@ -109,7 +109,7 @@ static const mi_tld_t tld_empty = {
false,
NULL,
{ MI_SEGMENT_SPAN_QUEUES_EMPTY, 0, 0, 0, 0, 0, 0, NULL, tld_empty_stats }, // segments
{ 0, tld_empty_stats }, // os
{ 0, -1, tld_empty_stats }, // os
{ MI_STATS_NULL } // stats
};
@ -123,7 +123,7 @@ static mi_tld_t tld_main = {
0, false,
&_mi_heap_main,
{ MI_SEGMENT_SPAN_QUEUES_EMPTY, 0, 0, 0, 0, 0, 0, NULL, tld_main_stats }, // segments
{ 0, tld_main_stats }, // os
{ 0, -1, tld_main_stats }, // os
{ MI_STATS_NULL } // stats
};
@ -242,6 +242,7 @@ static bool _mi_heap_init(void) {
heap->tld = tld;
tld->heap_backing = heap;
tld->segments.stats = &tld->stats;
tld->os.numa_node = -1;
tld->os.stats = &tld->stats;
_mi_heap_default = heap;
}

View file

@ -811,7 +811,7 @@ static void* mi_os_alloc_huge_os_pagesx(size_t size, int numa_node)
params[0].Pointer = &reqs;
params[1].Type = 5; // == MemExtendedParameterAttributeFlags;
params[1].ULong64 = MEM_EXTENDED_PARAMETER_NONPAGED_HUGE;
size_t param_count = 2;
ULONG param_count = 2;
if (numa_node >= 0) {
param_count++;
params[2].Type = MemExtendedParameterNumaNode;
@ -832,7 +832,7 @@ static void* mi_os_alloc_huge_os_pagesx(size_t size, int numa_node)
if (pVirtualAlloc2 != NULL) {
params[0].Type = MemExtendedParameterAddressRequirements;
params[0].Pointer = &reqs;
size_t param_count = 1;
ULONG param_count = 1;
if (numa_node >= 0) {
param_count++;
params[1].Type = MemExtendedParameterNumaNode;
@ -883,7 +883,7 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, size_t* psize) {
}
#ifdef WIN32
static int mi_os_numa_nodex(void) {
static int mi_os_numa_nodex() {
PROCESSOR_NUMBER pnum;
USHORT numa_node = 0;
GetCurrentProcessorNumberEx(&pnum);
@ -897,12 +897,42 @@ static int mi_os_numa_node_countx(void) {
return (int)(numa_max + 1);
}
#elif MI_HAS_NUMA
#include <numa.h>
#include <dirent.h>
#include <stdlib.h>
#include <numaif.h>
static int mi_os_numa_nodex(void) {
return numa_preferred();
#define MI_MAX_MASK (4) // support at most 256 nodes
unsigned long mask[MI_MAX_MASK];
memset(mask,0,MI_MAX_MASK*sizeof(long));
int mode = 0;
long err = get_mempolicy(&mode, mask, MI_MAX_MASK*sizeof(long)*8, NULL, 0 /* thread policy */);
if (err != 0) return 0;
// find the lowest bit that is set
for(int i = 0; i < MI_MAX_MASK; i++) {
for(int j = 0; j < (int)(sizeof(long)*8); j++) {
if ((mask[i] & (1UL << j)) != 0) {
return (i*sizeof(long)*8 + j);
}
}
}
return 0;
}
static int mi_os_numa_node_countx(void) {
return (numa_max_node() + 1);
DIR* d = opendir("/sys/devices/system/node");
if (d==NULL) return 1;
struct dirent* de;
int max_node_num = 0;
while ((de = readdir(d)) != NULL) {
int node_num;
if (strncmp(de->d_name, "node", 4) == 0) {
node_num = (int)strtol(de->d_name+4, NULL, 0);
if (max_node_num < node_num) max_node_num = node_num;
}
}
closedir(d);
return (max_node_num + 1);
}
#else
static int mi_os_numa_nodex(void) {
@ -914,19 +944,29 @@ static int mi_os_numa_node_countx(void) {
#endif
int _mi_os_numa_node_count(void) {
long ncount = mi_os_numa_node_countx();
static int numa_node_count = 0;
if (mi_unlikely(numa_node_count <= 0)) {
int ncount = mi_os_numa_node_countx();
// never more than max numa node and at least 1
long nmax = 1 + mi_option_get(mi_option_max_numa_node);
int nmax = 1 + (int)mi_option_get(mi_option_max_numa_node);
if (ncount > nmax) ncount = nmax;
if (ncount <= 0) ncount = 1;
return ncount;
numa_node_count = ncount;
}
mi_assert_internal(numa_node_count >= 1);
return numa_node_count;
}
int _mi_os_numa_node(void) {
int _mi_os_numa_node(mi_os_tld_t* tld) {
if (mi_unlikely(tld->numa_node < 0)) {
int nnode = mi_os_numa_nodex();
// never more than the node count
int ncount = _mi_os_numa_node_count();
if (nnode >= ncount) { nnode = nnode % ncount; }
return nnode;
if (nnode < 0) nnode = 0;
tld->numa_node = nnode;
}
mi_assert_internal(tld->numa_node >= 0 && tld->numa_node < _mi_os_numa_node_count());
return tld->numa_node;
}