From 1d0c7a8bbc7a3b2378c0fdc2f47366a99c659a7b Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 9 Feb 2021 14:54:54 +0000 Subject: [PATCH] allowed vmprim.alloc_heap() to create a bigger heap than requested. enhanced the standard implementation(std.c) to attempt HUGETLB if the requested heap size is over 1/2 of the huge page size --- bin/main-s.c | 16 ++------- bin/main.c | 7 ---- lib/gc.c | 6 ++++ lib/hcl-c.c | 1 + lib/hcl-s.c | 24 ++------------ lib/hcl-s.h | 4 +-- lib/hcl.c | 7 ++-- lib/hcl.h | 3 +- lib/heap.c | 14 +++++--- lib/std.c | 94 ++++++++++++++++++++++++++++++++++++++++------------ 10 files changed, 98 insertions(+), 78 deletions(-) diff --git a/bin/main-s.c b/bin/main-s.c index 7352067..1e75c68 100644 --- a/bin/main-s.c +++ b/bin/main-s.c @@ -504,7 +504,6 @@ int main (int argc, char* argv[]) static hcl_bopt_lng_t lopt[] = { { ":log", 'l' }, - { "large-pages", '\0' }, { ":worker-max-count", '\0' }, { ":worker-stack-size", '\0' }, { ":worker-idle-timeout", '\0' }, @@ -535,8 +534,6 @@ int main (int argc, char* argv[]) hcl_ntime_t worker_idle_timeout = { 0, 0 }; hcl_oow_t actor_heap_size = MIN_ACTOR_HEAP_SIZE; hcl_ntime_t actor_max_runtime = { 0, 0 }; - int large_pages = 0; - hcl_bitmask_t trait; setlocale (LC_ALL, ""); @@ -557,15 +554,11 @@ int main (int argc, char* argv[]) case 'm': actor_heap_size = strtoul(opt.arg, HCL_NULL, 0); - if (actor_heap_size <= MIN_ACTOR_HEAP_SIZE) actor_heap_size = MIN_ACTOR_HEAP_SIZE; + if (actor_heap_size > 0 && actor_heap_size <= MIN_ACTOR_HEAP_SIZE) actor_heap_size = MIN_ACTOR_HEAP_SIZE; break; case '\0': - if (hcl_comp_bcstr(opt.lngopt, "large-pages") == 0) - { - large_pages = 1; - } - else if (hcl_comp_bcstr(opt.lngopt, "worker-max-count") == 0) + if (hcl_comp_bcstr(opt.lngopt, "worker-max-count") == 0) { worker_max_count = strtoul(opt.arg, HCL_NULL, 0); } @@ -646,11 +639,6 @@ int main (int argc, char* argv[]) if (handle_incpath(server, incpath) <= -1) goto oops; } - hcl_server_getoption (server, HCL_SERVER_TRAIT, &trait); - if (large_pages) trait |= HCL_SERVER_TRAIT_USE_LARGE_PAGES; - else trait &= ~HCL_SERVER_TRAIT_USE_LARGE_PAGES; - hcl_server_setoption (server, HCL_SERVER_TRAIT, &trait); - hcl_server_setoption (server, HCL_SERVER_WORKER_MAX_COUNT, &worker_max_count); hcl_server_setoption (server, HCL_SERVER_WORKER_STACK_SIZE, &worker_stack_size); hcl_server_setoption (server, HCL_SERVER_WORKER_IDLE_TIMEOUT, &worker_idle_timeout); diff --git a/bin/main.c b/bin/main.c index 25a62ef..8cb7429 100644 --- a/bin/main.c +++ b/bin/main.c @@ -665,7 +665,6 @@ int main (int argc, char* argv[]) { ":heapsize", '\0' }, { ":log", 'l' }, - { "large-pages", '\0' }, { HCL_NULL, '\0' } }; static hcl_bopt_t opt = @@ -677,7 +676,6 @@ int main (int argc, char* argv[]) const char* logopt = HCL_NULL; hcl_oow_t heapsize = DEFAULT_HEAPSIZE; int verbose = 0; - int large_pages = 0; #if defined(HCL_BUILD_DEBUG) const char* dbgopt = HCL_NULL; @@ -711,11 +709,6 @@ int main (int argc, char* argv[]) heapsize = strtoul(opt.arg, HCL_NULL, 0); break; } - else if (hcl_comp_bcstr(opt.lngopt, "large-pages") == 0) - { - large_pages = 1; - break; - } #if defined(HCL_BUILD_DEBUG) else if (hcl_comp_bcstr(opt.lngopt, "debug") == 0) { diff --git a/lib/gc.c b/lib/gc.c index 57672e1..6c49142 100644 --- a/lib/gc.c +++ b/lib/gc.c @@ -740,6 +740,12 @@ int hcl_ignite (hcl_t* hcl) { hcl_oow_t i; + if (!hcl->heap) + { + hcl->heap = hcl_makeheap(hcl, hcl->_reqheapsz); + if (HCL_UNLIKELY(!hcl->heap)) return -1; + } + if (!hcl->_nil) { hcl->_nil = hcl_makenil(hcl); diff --git a/lib/hcl-c.c b/lib/hcl-c.c index ed74654..12ba9e5 100644 --- a/lib/hcl-c.c +++ b/lib/hcl-c.c @@ -816,6 +816,7 @@ hcl_client_t* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_p return HCL_NULL; } + /* replace the vmprim.log_write function */ hcl->vmprim.log_write = log_write_for_dummy; xtn = (client_hcl_xtn_t*)hcl_getxtn(hcl); diff --git a/lib/hcl-s.c b/lib/hcl-s.c index 7cb37c2..8aebd8e 100644 --- a/lib/hcl-s.c +++ b/lib/hcl-s.c @@ -653,30 +653,10 @@ static void fini_hcl (hcl_t* hcl) hcl_server_proto_t* hcl_server_proto_open (hcl_oow_t xtnsize, hcl_server_worker_t* worker) { hcl_server_proto_t* proto; - hcl_vmprim_t vmprim; hcl_cb_t hclcb; worker_hcl_xtn_t* xtn; hcl_bitmask_t trait; -#if 0 - HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim)); - if (worker->server->cfg.trait & HCL_SERVER_TRAIT_USE_LARGE_PAGES) - { - vmprim.alloc_heap = hcl_vmprim_alloc_heap; - vmprim.free_heap = hcl_vmprim_free_heap; - } - vmprim.log_write = log_write; - vmprim.syserrstrb = hcl_vmprim_syserrstrb; - vmprim.assertfail = hcl_vmprim_assertfail; - vmprim.dl_startup = hcl_vmprim_dl_startup; - vmprim.dl_cleanup = hcl_vmprim_dl_cleanup; - vmprim.dl_open = hcl_vmprim_dl_open; - vmprim.dl_close = hcl_vmprim_dl_close; - vmprim.dl_getsym = hcl_vmprim_dl_getsym; - vmprim.vm_gettime = hcl_vmprim_vm_gettime; - vmprim.vm_sleep = hcl_vmprim_vm_sleep; -#endif - proto = (hcl_server_proto_t*)hcl_server_allocmem(worker->server, HCL_SIZEOF(*proto)); if (!proto) return HCL_NULL; @@ -684,11 +664,10 @@ hcl_server_proto_t* hcl_server_proto_open (hcl_oow_t xtnsize, hcl_server_worker_ proto->worker = worker; proto->exec_runtime_event_index = HCL_TMR_INVALID_INDEX; - /* TODO: LARGE_PAGES */ proto->hcl = hcl_openstdwithmmgr(hcl_server_getmmgr(proto->worker->server), HCL_SIZEOF(*xtn), worker->server->cfg.actor_heap_size, HCL_NULL); if (!proto->hcl) goto oops; - /* change the log_write primitive forcibly */ + /* replace the vmprim.log_write function */ proto->hcl->vmprim.log_write = log_write; xtn = (worker_hcl_xtn_t*)hcl_getxtn(proto->hcl); @@ -1544,6 +1523,7 @@ hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_p hcl = hcl_openstdwithmmgr(mmgr, HCL_SIZEOF(*xtn), 2048, errnum); if (!hcl) goto oops; + /* replace the vmprim.log_write function */ hcl->vmprim.log_write = log_write_for_dummy; tmr = hcl_tmr_open(hcl, 0, 1024); /* TOOD: make the timer's default size configurable */ diff --git a/lib/hcl-s.h b/lib/hcl-s.h index 2d1ab97..ee10a8e 100644 --- a/lib/hcl-s.h +++ b/lib/hcl-s.h @@ -51,10 +51,8 @@ enum hcl_server_trait_t { #if defined(HCL_BUILD_DEBUG) HCL_SERVER_TRAIT_DEBUG_GC = (1 << 0), - HCL_SERVER_TRAIT_DEBUG_BIGINT = (1 << 1), + HCL_SERVER_TRAIT_DEBUG_BIGINT = (1 << 1) #endif - - HCL_SERVER_TRAIT_USE_LARGE_PAGES = (1 << 2) }; typedef enum hcl_server_trait_t hcl_server_trait_t; diff --git a/lib/hcl.c b/lib/hcl.c index 39cd67b..779e1bb 100644 --- a/lib/hcl.c +++ b/lib/hcl.c @@ -157,14 +157,13 @@ int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t hcl->proc_map_free_first = -1; hcl->proc_map_free_last = -1; - hcl->heap = hcl_makeheap(hcl, heapsz); - if (HCL_UNLIKELY(!hcl->heap)) goto oops; + /* remember the requested heap size. but push back the actuall heap creation to hcl_ignite() */ + hcl->_reqheapsz = heapsz; if (hcl->vmprim.dl_startup) hcl->vmprim.dl_startup (hcl); return 0; oops: - if (hcl->heap) hcl_killheap (hcl, hcl->heap); if (modtab_inited) hcl_rbt_fini (&hcl->modtab); if (hcl->gci.stack.ptr) { @@ -309,7 +308,7 @@ void hcl_fini (hcl_t* hcl) hcl->gci.stack.len = 0; } - hcl_killheap (hcl, hcl->heap); + if (hcl->heap) hcl_killheap (hcl, hcl->heap); if (hcl->log.ptr) { diff --git a/lib/hcl.h b/lib/hcl.h index 8db50b3..497928d 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -918,7 +918,7 @@ typedef enum hcl_log_mask_t hcl_log_mask_t; typedef void* (*hcl_alloc_heap_t) ( hcl_t* hcl, - hcl_oow_t size + hcl_oow_t* size /* [IN] requested size, [OUT] allocated size */ ); typedef void (*hcl_free_heap_t) ( @@ -1392,6 +1392,7 @@ struct hcl_t } log; /* ========================= */ + hcl_oow_t _reqheapsz; hcl_heap_t* heap; /* ========================= */ diff --git a/lib/heap.c b/lib/heap.c index 4fd4c96..b52ba3a 100644 --- a/lib/heap.c +++ b/lib/heap.c @@ -44,8 +44,10 @@ static void xma_free (hcl_mmgr_t* mmgr, void* ptr) hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size) { hcl_heap_t* heap; + hcl_oow_t alloc_size; - heap = (hcl_heap_t*)hcl->vmprim.alloc_heap(hcl, HCL_SIZEOF(*heap) + size); + alloc_size = HCL_SIZEOF(*heap) + size; + heap = (hcl_heap_t*)hcl->vmprim.alloc_heap(hcl, &alloc_size); if (HCL_UNLIKELY(!heap)) { const hcl_ooch_t* oldmsg = hcl_backuperrmsg(hcl); @@ -53,11 +55,13 @@ hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size) return HCL_NULL; } - HCL_MEMSET (heap, 0, HCL_SIZEOF(*heap) + size); + /* the vmprim.alloc_heap() function is allowed to create a bigger heap than the requested size. + * if the created heap is bigger than requested, the heap will be utilized in full. */ + HCL_ASSERT (hcl, alloc_size >= HCL_SIZEOF(*heap) + size); + HCL_MEMSET (heap, 0, alloc_size); heap->base = (hcl_uint8_t*)(heap + 1); - heap->size = size; - + heap->size = alloc_size; if (size <= 0) { @@ -71,7 +75,7 @@ hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size) if (HCL_UNLIKELY(!heap->xma)) { hcl->vmprim.free_heap (hcl, heap); - hcl_seterrbfmt (hcl, HCL_ESYSMEM, "unable to allocate xma"); + hcl_seterrbfmt (hcl, HCL_ESYSMEM, "unable to allocate a memory manager over a heap"); return HCL_NULL; } diff --git a/lib/std.c b/lib/std.c index 2f6b8b1..d130610 100644 --- a/lib/std.c +++ b/lib/std.c @@ -975,7 +975,36 @@ static void _assertfail (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* fil * HEAP ALLOCATION * ----------------------------------------------------------------- */ -static void* alloc_heap (hcl_t* hcl, hcl_oow_t size) +static int get_huge_page_size (hcl_t* hcl, hcl_oow_t* page_size) +{ + FILE* fp; + char buf[256]; + + fp = fopen("/proc/meminfo", "r"); + if (!fp) return -1; + + while (!feof(fp)) + { + if (fgets(buf, sizeof(buf) - 1, fp) == NULL) goto oops; + + if (strncmp(buf, "Hugepagesize: ", 13) == 0) + { + unsigned long int tmp; + tmp = strtoul(&buf[13], NULL, 10); + if (tmp == HCL_TYPE_MAX(unsigned long int) && errno == ERANGE) goto oops; + + *page_size = tmp * 1024; /* KBytes to Bytes */ + fclose (fp); + return 0; + } + } + +oops: + fclose (fp); + return -1; +} + +static void* alloc_heap (hcl_t* hcl, hcl_oow_t* size) { #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) && defined(MAP_ANONYMOUS) /* It's called via hcl_makeheap() when HCL creates a GC heap. @@ -990,37 +1019,60 @@ static void* alloc_heap (hcl_t* hcl, hcl_oow_t size) hcl_oow_t* ptr; int flags; - hcl_oow_t actual_size; + hcl_oow_t req_size, align, aligned_size; + req_size = HCL_SIZEOF(hcl_oow_t) + *size; flags = MAP_PRIVATE | MAP_ANONYMOUS; - #if defined(MAP_HUGETLB) - flags |= MAP_HUGETLB; - #endif - #if defined(MAP_UNINITIALIZED) flags |= MAP_UNINITIALIZED; #endif - actual_size = HCL_SIZEOF(hcl_oow_t) + size; - actual_size = HCL_ALIGN_POW2(actual_size, 2 * 1024 * 1024); - ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0); + #if defined(MAP_HUGETLB) + if (get_huge_page_size(hcl, &align) <= -1) align = 2 * 1024 * 1024; /* default to 2MB */ + if (req_size > align / 2) + { + /* if the requested size is large enough, attempt HUGETLB */ + flags |= MAP_HUGETLB; + } + else + { + align = sysconf(_SC_PAGESIZE); + } + #else + align = sysconf(_SC_PAGESIZE); + #endif + + aligned_size = HCL_ALIGN_POW2(req_size, align); + ptr = (hcl_oow_t*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, flags, -1, 0); + #if defined(MAP_HUGETLB) + if (ptr == MAP_FAILED && (flags & MAP_HUGETLB)) + { + flags &= ~MAP_HUGETLB; + align = sysconf(_SC_PAGESIZE); + aligned_size = HCL_ALIGN_POW2(req_size, align); + ptr = (hcl_oow_t*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (ptr == MAP_FAILED) + { + hcl_seterrwithsyserr (hcl, 0, errno); + return HCL_NULL; + } + } + #else if (ptr == MAP_FAILED) { - #if defined(MAP_HUGETLB) - flags &= ~MAP_HUGETLB; - ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0); - if (ptr == MAP_FAILED) return HCL_NULL; - #else + hcl_seterrwithsyserr (hcl, 0, errno); return HCL_NULL; - #endif } - *ptr = actual_size; + #endif + + *ptr = aligned_size; + *size = aligned_size - HCL_SIZEOF(hcl_oow_t); return (void*)(ptr + 1); #else - return HCL_MMGR_ALLOC(hcl->_mmgr, size); + return HCL_MMGR_ALLOC(hcl->_mmgr, *size); #endif } @@ -2864,6 +2916,7 @@ static void cb_vm_cleanup (hcl_t* hcl) MUTEX_DESTROY (&xtn->ev.reg.smtx); #endif } + /* ----------------------------------------------------------------- * STANDARD HCL * ----------------------------------------------------------------- */ @@ -2875,11 +2928,8 @@ hcl_t* hcl_openstdwithmmgr (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_oow_t heaps hcl_cb_t cb; HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim)); - //if (large_pages) - //{ - vmprim.alloc_heap = alloc_heap; - vmprim.free_heap = free_heap; - //} + vmprim.alloc_heap = alloc_heap; + vmprim.free_heap = free_heap; vmprim.log_write = log_write; vmprim.syserrstrb = _syserrstrb; vmprim.assertfail = _assertfail;