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
This commit is contained in:
hyung-hwan 2021-02-09 14:54:54 +00:00
parent aa8f8fac2d
commit 1d0c7a8bbc
10 changed files with 98 additions and 78 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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)
{

View File

@ -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;
/* ========================= */

View File

@ -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;
}

View File

@ -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)
{
#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;
}
#else
if (ptr == MAP_FAILED)
{
hcl_seterrwithsyserr (hcl, 0, errno);
return HCL_NULL;
}
#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.log_write = log_write;
vmprim.syserrstrb = _syserrstrb;
vmprim.assertfail = _assertfail;