From 024ccf6826d87ead1722241d9640cc42368a793e Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Wed, 7 Apr 2021 01:45:14 +0300 Subject: [PATCH] mdbx: extract `mdbx_get_sysraminfo()`. Change-Id: I8821009572d275a3b5d2d8729f605b115a80e50a --- mdbx.h | 6 +++ src/core.c | 120 ++++------------------------------------------- src/internals.h | 17 +++++++ src/osal.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 112 deletions(-) diff --git a/mdbx.h b/mdbx.h index 3568a444..5b894cfa 100644 --- a/mdbx.h +++ b/mdbx.h @@ -2858,6 +2858,12 @@ LIBMDBX_INLINE_API(int, mdbx_env_get_maxdbs, * page and usually exactly match it. */ MDBX_NOTHROW_PURE_FUNCTION LIBMDBX_API size_t mdbx_default_pagesize(void); +/** \brief Returns basic information about system RAM. + * \ingroup c_statinfo + */ +LIBMDBX_API int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages, + intptr_t *avail_pages); + /** \brief Get the maximum size of keys can write. * \ingroup c_statinfo * diff --git a/src/core.c b/src/core.c index 682749e2..87535722 100644 --- a/src/core.c +++ b/src/core.c @@ -40,23 +40,6 @@ /*------------------------------------------------------------------------------ * Internal inline functions */ -MDBX_NOTHROW_CONST_FUNCTION static unsigned log2n(size_t value) { - assert(value > 0 && value < INT32_MAX && is_powerof2(value)); - assert((value & -(int32_t)value) == value); -#if __GNUC_PREREQ(4, 1) || __has_builtin(__builtin_ctzl) - return __builtin_ctzl(value); -#elif defined(_MSC_VER) - unsigned long index; - _BitScanForward(&index, (unsigned long)value); - return index; -#else - static const uint8_t debruijn_ctz32[32] = { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; - return debruijn_ctz32[(uint32_t)(value * 0x077CB531u) >> 27]; -#endif -} - MDBX_NOTHROW_CONST_FUNCTION static unsigned branchless_abs(int value) { assert(value > INT_MIN); const unsigned expanded_sign = @@ -11584,61 +11567,12 @@ __cold int mdbx_is_readahead_reasonable(size_t volume, intptr_t redundancy) { if (volume <= 1024 * 1024 * 4ul) return MDBX_RESULT_TRUE; - const intptr_t pagesize = mdbx_syspagesize(); - if (unlikely(pagesize < MIN_PAGESIZE || !is_powerof2(pagesize))) - return MDBX_INCOMPATIBLE; + intptr_t pagesize, total_ram_pages; + int err = mdbx_get_sysraminfo(&pagesize, &total_ram_pages, nullptr); + if (unlikely(err != MDBX_SUCCESS)) + return err; -#if defined(_WIN32) || defined(_WIN64) - MEMORYSTATUSEX info; - memset(&info, 0, sizeof(info)); - info.dwLength = sizeof(info); - if (!GlobalMemoryStatusEx(&info)) - return GetLastError(); -#endif const int log2page = log2n(pagesize); - -#if defined(_WIN32) || defined(_WIN64) - const intptr_t total_ram_pages = (intptr_t)(info.ullTotalPhys >> log2page); -#elif defined(_SC_PHYS_PAGES) - const intptr_t total_ram_pages = sysconf(_SC_PHYS_PAGES); - if (total_ram_pages == -1) - return errno; -#elif defined(_SC_AIX_REALMEM) - const intptr_t total_ram_Kb = sysconf(_SC_AIX_REALMEM); - if (total_ram_Kb == -1) - return errno; - const intptr_t total_ram_pages = (total_ram_Kb << 10) >> log2page; -#elif defined(HW_USERMEM) || defined(HW_PHYSMEM64) || defined(HW_MEMSIZE) || \ - defined(HW_PHYSMEM) - size_t ram, len = sizeof(ram); - static const int mib[] = { - CTL_HW, -#if defined(HW_USERMEM) - HW_USERMEM -#elif defined(HW_PHYSMEM64) - HW_PHYSMEM64 -#elif defined(HW_MEMSIZE) - HW_MEMSIZE -#else - HW_PHYSMEM -#endif - }; - if (sysctl( -#ifdef SYSCTL_LEGACY_NONCONST_MIB - (int *) -#endif - mib, - ARRAY_LENGTH(mib), &ram, &len, NULL, 0) != 0) - return errno; - if (len != sizeof(ram)) - return MDBX_ENOSYS; - const intptr_t total_ram_pages = (intptr_t)(ram >> log2page); -#else -#error "FIXME: Get User-accessible or physical RAM" -#endif - if (total_ram_pages < 1) - return MDBX_ENOSYS; - const intptr_t volume_pages = (volume + pagesize - 1) >> log2page; const intptr_t redundancy_pages = (redundancy < 0) ? -(intptr_t)((-redundancy + pagesize - 1) >> log2page) @@ -11647,48 +11581,10 @@ __cold int mdbx_is_readahead_reasonable(size_t volume, intptr_t redundancy) { volume_pages + redundancy_pages >= total_ram_pages) return MDBX_RESULT_FALSE; -#if defined(_WIN32) || defined(_WIN64) - const intptr_t avail_ram_pages = (intptr_t)(info.ullAvailPhys >> log2page); -#elif defined(_SC_AVPHYS_PAGES) - const intptr_t avail_ram_pages = sysconf(_SC_AVPHYS_PAGES); - if (avail_ram_pages == -1) - return errno; -#elif defined(__MACH__) - mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - vm_statistics_data_t vmstat; - mach_port_t mport = mach_host_self(); - kern_return_t kerr = host_statistics(mach_host_self(), HOST_VM_INFO, - (host_info_t)&vmstat, &count); - mach_port_deallocate(mach_task_self(), mport); - if (unlikely(kerr != KERN_SUCCESS)) - return MDBX_ENOSYS; - const intptr_t avail_ram_pages = vmstat.free_count; -#elif defined(VM_TOTAL) || defined(VM_METER) - struct vmtotal info; - size_t len = sizeof(info); - static const int mib[] = { - CTL_VM, -#if defined(VM_TOTAL) - VM_TOTAL -#elif defined(VM_METER) - VM_METER -#endif - }; - if (sysctl( -#ifdef SYSCTL_LEGACY_NONCONST_MIB - (int *) -#endif - mib, - ARRAY_LENGTH(mib), &info, &len, NULL, 0) != 0) - return errno; - if (len != sizeof(info)) - return MDBX_ENOSYS; - const intptr_t avail_ram_pages = info.t_free; -#else -#error "FIXME: Get Available RAM" -#endif - if (avail_ram_pages < 1) - return MDBX_ENOSYS; + intptr_t avail_ram_pages; + err = mdbx_get_sysraminfo(nullptr, nullptr, &avail_ram_pages); + if (unlikely(err != MDBX_SUCCESS)) + return err; return (volume_pages + redundancy_pages >= avail_ram_pages) ? MDBX_RESULT_FALSE diff --git a/src/internals.h b/src/internals.h index fd4743a5..df9c7c09 100644 --- a/src/internals.h +++ b/src/internals.h @@ -1389,6 +1389,23 @@ ceil_powerof2(size_t value, size_t granularity) { return floor_powerof2(value + granularity - 1, granularity); } +MDBX_NOTHROW_CONST_FUNCTION static __maybe_unused unsigned log2n(size_t value) { + assert(value > 0 && value < INT32_MAX && is_powerof2(value)); + assert((value & -(int32_t)value) == value); +#if __GNUC_PREREQ(4, 1) || __has_builtin(__builtin_ctzl) + return __builtin_ctzl(value); +#elif defined(_MSC_VER) + unsigned long index; + _BitScanForward(&index, (unsigned long)value); + return index; +#else + static const uint8_t debruijn_ctz32[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; + return debruijn_ctz32[(uint32_t)(value * 0x077CB531u) >> 27]; +#endif +} + /* Only a subset of the mdbx_env flags can be changed * at runtime. Changing other flags requires closing the * environment and re-opening it with the new flags. */ diff --git a/src/osal.c b/src/osal.c index 2b27f457..ac6dba88 100644 --- a/src/osal.c +++ b/src/osal.c @@ -2393,3 +2393,124 @@ __cold MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void) { return bin; } + +__cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages, + intptr_t *avail_pages) { + if (!page_size && !total_pages && !avail_pages) + return MDBX_EINVAL; + if (total_pages) + *total_pages = -1; + if (avail_pages) + *avail_pages = -1; + + const intptr_t pagesize = mdbx_syspagesize(); + if (page_size) + *page_size = pagesize; + if (unlikely(pagesize < MIN_PAGESIZE || !is_powerof2(pagesize))) + return MDBX_INCOMPATIBLE; + + __maybe_unused const int log2page = log2n(pagesize); + assert(pagesize == (INT64_C(1) << log2page)); + (void)log2page; + +#if defined(_WIN32) || defined(_WIN64) + MEMORYSTATUSEX info; + memset(&info, 0, sizeof(info)); + info.dwLength = sizeof(info); + if (!GlobalMemoryStatusEx(&info)) + return GetLastError(); +#endif + + if (total_pages) { +#if defined(_WIN32) || defined(_WIN64) + const intptr_t total_ram_pages = (intptr_t)(info.ullTotalPhys >> log2page); +#elif defined(_SC_PHYS_PAGES) + const intptr_t total_ram_pages = sysconf(_SC_PHYS_PAGES); + if (total_ram_pages == -1) + return errno; +#elif defined(_SC_AIX_REALMEM) + const intptr_t total_ram_Kb = sysconf(_SC_AIX_REALMEM); + if (total_ram_Kb == -1) + return errno; + const intptr_t total_ram_pages = (total_ram_Kb << 10) >> log2page; +#elif defined(HW_USERMEM) || defined(HW_PHYSMEM64) || defined(HW_MEMSIZE) || \ + defined(HW_PHYSMEM) + size_t ram, len = sizeof(ram); + static const int mib[] = { + CTL_HW, +#if defined(HW_USERMEM) + HW_USERMEM +#elif defined(HW_PHYSMEM64) + HW_PHYSMEM64 +#elif defined(HW_MEMSIZE) + HW_MEMSIZE +#else + HW_PHYSMEM +#endif + }; + if (sysctl( +#ifdef SYSCTL_LEGACY_NONCONST_MIB + (int *) +#endif + mib, + ARRAY_LENGTH(mib), &ram, &len, NULL, 0) != 0) + return errno; + if (len != sizeof(ram)) + return MDBX_ENOSYS; + const intptr_t total_ram_pages = (intptr_t)(ram >> log2page); +#else +#error "FIXME: Get User-accessible or physical RAM" +#endif + *total_pages = total_ram_pages; + if (total_ram_pages < 1) + return MDBX_ENOSYS; + } + + if (avail_pages) { +#if defined(_WIN32) || defined(_WIN64) + const intptr_t avail_ram_pages = (intptr_t)(info.ullAvailPhys >> log2page); +#elif defined(_SC_AVPHYS_PAGES) + const intptr_t avail_ram_pages = sysconf(_SC_AVPHYS_PAGES); + if (avail_ram_pages == -1) + return errno; +#elif defined(__MACH__) + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + vm_statistics_data_t vmstat; + mach_port_t mport = mach_host_self(); + kern_return_t kerr = host_statistics(mach_host_self(), HOST_VM_INFO, + (host_info_t)&vmstat, &count); + mach_port_deallocate(mach_task_self(), mport); + if (unlikely(kerr != KERN_SUCCESS)) + return MDBX_ENOSYS; + const intptr_t avail_ram_pages = vmstat.free_count; +#elif defined(VM_TOTAL) || defined(VM_METER) + struct vmtotal info; + size_t len = sizeof(info); + static const int mib[] = { + CTL_VM, +#if defined(VM_TOTAL) + VM_TOTAL +#elif defined(VM_METER) + VM_METER +#endif + }; + if (sysctl( +#ifdef SYSCTL_LEGACY_NONCONST_MIB + (int *) +#endif + mib, + ARRAY_LENGTH(mib), &info, &len, NULL, 0) != 0) + return errno; + if (len != sizeof(info)) + return MDBX_ENOSYS; + const intptr_t avail_ram_pages = info.t_free; +#else +#error "FIXME: Get Available RAM" +#endif + *avail_pages = avail_ram_pages; + if (avail_ram_pages < 1) + return MDBX_ENOSYS; + } + + return MDBX_SUCCESS; +}