diff options
author | Ben Gamari <ben@smart-cactus.org> | 2020-11-25 16:18:54 -0500 |
---|---|---|
committer | Matthew Pickering <matthewtpickering@gmail.com> | 2021-03-01 21:12:41 +0000 |
commit | f02fb193bd59862840fa3946a20923298dac0745 (patch) | |
tree | 0bb7e6ecb734ee77d90c91d8228d35070606230b | |
parent | a9f23793126251844944e00bca8e84370c759aa7 (diff) | |
download | haskell-f02fb193bd59862840fa3946a20923298dac0745.tar.gz |
rts: Add support for hugepages
Co-authored-by: Matthew Pickering <matthewtpickering@gmail.com>
-rw-r--r-- | includes/rts/Constants.h | 2 | ||||
-rw-r--r-- | includes/rts/Flags.h | 1 | ||||
-rw-r--r-- | rts/RtsFlags.c | 19 | ||||
-rw-r--r-- | rts/posix/OSMem.c | 24 |
4 files changed, 38 insertions, 8 deletions
diff --git a/includes/rts/Constants.h b/includes/rts/Constants.h index 043099bd1a..6efdd977d8 100644 --- a/includes/rts/Constants.h +++ b/includes/rts/Constants.h @@ -170,7 +170,7 @@ #define BLOCK_SHIFT 12 /* The size of a megablock (2^MBLOCK_SHIFT bytes) */ -#define MBLOCK_SHIFT 20 +#define MBLOCK_SHIFT 21 /* ----------------------------------------------------------------------------- Bitmap/size fields (used in info tables) diff --git a/includes/rts/Flags.h b/includes/rts/Flags.h index 35b45b0940..5b4e29fe3f 100644 --- a/includes/rts/Flags.h +++ b/includes/rts/Flags.h @@ -89,6 +89,7 @@ typedef struct _GC_FLAGS { bool numa; /* Use NUMA */ StgWord numaMask; + bool hugepages; /* Enable hugepages support */ } GC_FLAGS; /* See Note [Synchronization of flags and base APIs] */ diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c index 380ccc3afc..f86191ed57 100644 --- a/rts/RtsFlags.c +++ b/rts/RtsFlags.c @@ -182,6 +182,7 @@ void initRtsFlagsDefaults(void) RtsFlags.GcFlags.allocLimitGrace = (100*1024) / BLOCK_SIZE; RtsFlags.GcFlags.numa = false; RtsFlags.GcFlags.numaMask = 1; + RtsFlags.GcFlags.hugepages = false; RtsFlags.GcFlags.ringBell = false; RtsFlags.GcFlags.longGCSync = 0; /* detection turned off */ @@ -517,6 +518,7 @@ usage_text[] = { #endif " -xq The allocation limit given to a thread after it receives", " an AllocationLimitExceeded exception. (default: 100k)", +" -xH Use hugepages to allocate huge", "", " -Mgrace=<n>", " The amount of allocation after the program receives a", @@ -1698,13 +1700,18 @@ error = true; */ case 'q': - OPTION_UNSAFE; - RtsFlags.GcFlags.allocLimitGrace - = decodeSize(rts_argv[arg], 3, BLOCK_SIZE, HS_INT_MAX) - / BLOCK_SIZE; - break; + OPTION_UNSAFE; + RtsFlags.GcFlags.allocLimitGrace + = decodeSize(rts_argv[arg], 3, BLOCK_SIZE, HS_INT_MAX) + / BLOCK_SIZE; + break; - default: + case 'H': + OPTION_SAFE; + RtsFlags.GcFlags.hugepages = true; + break; + + default: OPTION_SAFE; errorBelch("unknown RTS option: %s",rts_argv[arg]); error = true; diff --git a/rts/posix/OSMem.c b/rts/posix/OSMem.c index 30d9981f16..53ea69702d 100644 --- a/rts/posix/OSMem.c +++ b/rts/posix/OSMem.c @@ -60,6 +60,11 @@ # endif #endif +#define HUGEPAGE_SIZE (2*1024*1024) +// This constant is from linux/mman.h +#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT) +#define HUGEPAGE_FLAGS MAP_HUGETLB + #if !defined(darwin_HOST_OS) # undef RESERVE_FLAGS # if defined(MAP_GUARD) @@ -73,6 +78,9 @@ # endif #endif +int huge_tried = 0; +int huge_failed = 0; + static void *next_request = 0; void osMemInit(void) @@ -233,12 +241,24 @@ my_mmap (void *addr, W_ size, int operation) errorBelch("my_mmap(,,MEM_RESERVE) not supported on this platform"); # endif } else if (operation == MEM_COMMIT) { - flags = MAP_FIXED | MAP_ANON | MAP_PRIVATE; + flags = MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE; + if ( RtsFlags.GcFlags.hugepages && + (size & (HUGEPAGE_SIZE - 1)) == 0) { + huge_tried += 1; + flags |= HUGEPAGE_FLAGS; + } } else { flags = MAP_ANON | MAP_PRIVATE; } ret = mmap(addr, size, prot, flags, -1, 0); + // If the mmap failed, and we tried with HUGEPAGE_FLAGS + // then retry without. + if (ret == MAP_FAILED && flags & HUGEPAGE_FLAGS){ + huge_failed += 1; + flags &= ~HUGEPAGE_FLAGS; + ret = mmap(addr, size, prot, flags, -1, 0); + } # if defined(linux_HOST_OS) if (ret == MAP_FAILED && errno == EPERM) { // Linux may return EPERM if it tried to give us @@ -472,6 +492,7 @@ void setExecutable (void *p, W_ len, bool exec) #if defined(USE_LARGE_ADDRESS_SPACE) + static void * osTryReserveHeapMemory (W_ len, void *hint) { @@ -485,6 +506,7 @@ osTryReserveHeapMemory (W_ len, void *hint) and then we discard what we don't need */ base = my_mmap(hint, len + MBLOCK_SIZE, MEM_RESERVE); + if (base == NULL) return NULL; |