Browse Source

Enable huge page for posix platforms (#825)

This patch enables huge page support for posix platforms for performance
reason, if the request size to mmap is larger than 2MB, then we use madvise
to set some pages to huge page.
And add macro control to enable tracing the mmap/munmap.

Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
Wenyong Huang 4 năm trước cách đây
mục cha
commit
9281286181
1 tập tin đã thay đổi với 119 bổ sung12 xóa
  1. 119 12
      core/shared/platform/common/posix/posix_memmap.c

+ 119 - 12
core/shared/platform/common/posix/posix_memmap.c

@@ -5,24 +5,56 @@
 
 #include "platform_api_vmcore.h"
 
+#ifndef BH_ENABLE_TRACE_MMAP
+#define BH_ENABLE_TRACE_MMAP 0
+#endif
+
+#if BH_ENABLE_TRACE_MMAP != 0
+static size_t total_size_mmapped = 0;
+static size_t total_size_munmapped = 0;
+#endif
+
+#define HUGE_PAGE_SIZE (2 * 1024 * 1024)
+
+static inline uintptr_t
+round_up(uintptr_t v, uintptr_t b)
+{
+    uintptr_t m = b - 1;
+    return (v + m) & ~m;
+}
+
+static inline uintptr_t
+round_down(uintptr_t v, uintptr_t b)
+{
+    uintptr_t m = b - 1;
+    return v & ~m;
+}
+
 void *
 os_mmap(void *hint, size_t size, int prot, int flags)
 {
     int map_prot = PROT_NONE;
     int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
     uint64 request_size, page_size;
-    uint8 *addr;
+    uint8 *addr = MAP_FAILED;
     uint32 i;
 
     page_size = (uint64)getpagesize();
     request_size = (size + page_size - 1) & ~(page_size - 1);
 
+#if !defined(__APPLE__) && !defined(__NuttX__)
+    /* huge page isn't supported on MacOS and NuttX */
+    if (request_size >= HUGE_PAGE_SIZE)
+        /* apply one extra huge page */
+        request_size += HUGE_PAGE_SIZE;
+#endif
+
     if ((size_t)request_size < size)
         /* integer overflow */
         return NULL;
 
     if (request_size > 16 * (uint64)UINT32_MAX)
-        /* At most 16 G is allowed */
+        /* at most 16 G is allowed */
         return NULL;
 
     if (prot & MMAP_PROT_READ)
@@ -80,25 +112,93 @@ os_mmap(void *hint, size_t size, int prot, int flags)
                     os_munmap(addr, request_size);
                 }
                 else {
-                    /* reset next hint address */
+                    /* success, reset next hint address */
                     hint_addr += request_size;
-                    return addr;
+                    break;
                 }
             }
             hint_addr += BH_MB;
         }
     }
-#endif
-
-    /* try 5 times */
-    for (i = 0; i < 5; i++) {
-        addr = mmap(hint, request_size, map_prot, map_flags, -1, 0);
-        if (addr != MAP_FAILED)
-            break;
+#endif /* end of BUILD_TARGET_RISCV64_LP64D || BUILD_TARGET_RISCV64_LP64 */
+
+    /* memory has't been mapped or was mapped failed previously */
+    if (addr == MAP_FAILED) {
+        /* try 5 times */
+        for (i = 0; i < 5; i++) {
+            addr = mmap(hint, request_size, map_prot, map_flags, -1, 0);
+            if (addr != MAP_FAILED)
+                break;
+        }
     }
 
-    if (addr == MAP_FAILED)
+    if (addr == MAP_FAILED) {
+#if BH_ENABLE_TRACE_MMAP != 0
+        os_printf("mmap failed\n");
+#endif
         return NULL;
+    }
+
+#if BH_ENABLE_TRACE_MMAP != 0
+    total_size_mmapped += request_size;
+    os_printf("mmap return: %p with size: %zu, total_size_mmapped: %zu, "
+              "total_size_munmapped: %zu\n",
+              addr, request_size, total_size_mmapped, total_size_munmapped);
+#endif
+
+#if !defined(__APPLE__) && !defined(__NuttX__)
+    /* huge page isn't supported on MacOS and NuttX */
+    if (request_size > HUGE_PAGE_SIZE) {
+        uintptr_t huge_start, huge_end;
+        size_t prefix_size = 0, suffix_size = HUGE_PAGE_SIZE;
+
+        huge_start = round_up((uintptr_t)addr, HUGE_PAGE_SIZE);
+
+        if (huge_start > (uintptr_t)addr) {
+            prefix_size += huge_start - (uintptr_t)addr;
+            suffix_size -= huge_start - (uintptr_t)addr;
+        }
+
+        /* unmap one extra huge page */
+
+        if (prefix_size > 0) {
+            munmap(addr, prefix_size);
+#if BH_ENABLE_TRACE_MMAP != 0
+            total_size_munmapped += prefix_size;
+            os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, "
+                      "total_size_munmapped: %zu\n",
+                      addr, prefix_size, total_size_mmapped,
+                      total_size_munmapped);
+#endif
+        }
+        if (suffix_size > 0) {
+            munmap(addr + request_size - suffix_size, suffix_size);
+#if BH_ENABLE_TRACE_MMAP != 0
+            total_size_munmapped += suffix_size;
+            os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, "
+                      "total_size_munmapped: %zu\n",
+                      addr + request_size - suffix_size, suffix_size,
+                      total_size_mmapped, total_size_munmapped);
+#endif
+        }
+
+        addr = (uint8 *)huge_start;
+        request_size -= HUGE_PAGE_SIZE;
+
+        huge_end = round_down(huge_start + request_size, HUGE_PAGE_SIZE);
+        if (huge_end > huge_start) {
+            int ret = madvise((void *)huge_start, huge_end - huge_start,
+                              MADV_HUGEPAGE);
+            if (ret) {
+#if BH_ENABLE_TRACE_MMAP != 0
+                os_printf(
+                    "warning: madvise(%p, %lu) huge page failed, return %d\n",
+                    (void *)huge_start, huge_end - huge_start, ret);
+#endif
+            }
+        }
+    }
+#endif /* end of __APPLE__ || __NuttX__ */
 
     return addr;
 }
@@ -113,7 +213,14 @@ os_munmap(void *addr, size_t size)
         if (munmap(addr, request_size)) {
             os_printf("os_munmap error addr:%p, size:0x%" PRIx64 ", errno:%d\n",
                       addr, request_size, errno);
+            return;
         }
+#if BH_ENABLE_TRACE_MMAP != 0
+        total_size_munmapped += request_size;
+        os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, "
+                  "total_size_munmapped: %zu\n",
+                  addr, request_size, total_size_mmapped, total_size_munmapped);
+#endif
     }
 }