From 5f0ad641553818da9d0bd502b08915837adfffe0 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Sat, 24 Jun 2023 19:15:15 +0800 Subject: [PATCH] runtime: add new functions total_memory/0 and free_memory/0 (#18499) --- vlib/runtime/README.md | 1 + vlib/runtime/free_memory_impl_darwin.c.v | 34 +++++++++++++++++++++++ vlib/runtime/free_memory_impl_default.c.v | 5 ++++ vlib/runtime/free_memory_impl_linux.c.v | 10 +++++++ vlib/runtime/runtime_nix.c.v | 12 ++++++++ vlib/runtime/runtime_test.v | 14 ++++++++++ vlib/runtime/runtime_windows.c.v | 21 ++++++++++++++ 7 files changed, 97 insertions(+) create mode 100644 vlib/runtime/free_memory_impl_darwin.c.v create mode 100644 vlib/runtime/free_memory_impl_default.c.v create mode 100644 vlib/runtime/free_memory_impl_linux.c.v diff --git a/vlib/runtime/README.md b/vlib/runtime/README.md index 6d3fc226a0..ca2a982795 100644 --- a/vlib/runtime/README.md +++ b/vlib/runtime/README.md @@ -3,5 +3,6 @@ `runtime` provides access to functions describing the current platform: - whether it is 32bit or 64bit - how many CPUs/cores are available +- total/free physical memory - whether the platform is little endian or big endian - etc. diff --git a/vlib/runtime/free_memory_impl_darwin.c.v b/vlib/runtime/free_memory_impl_darwin.c.v new file mode 100644 index 0000000000..9c6c2f897f --- /dev/null +++ b/vlib/runtime/free_memory_impl_darwin.c.v @@ -0,0 +1,34 @@ +module runtime + +#include + +[typedef] +struct C.vm_size_t { +} + +[typedef] +struct C.vm_statistics64_data_t { + free_count u32 + purgeable_count u32 + speculative_count u32 + external_page_count u32 +} + +fn C.mach_host_self() C.host_t +fn C.host_page_size(host C.host_t, out_page_size &C.vm_size_t) int +fn C.host_statistics64(host C.host_t, flavor int, host_info_out &int, host_info_outCnt &u32) int + +fn free_memory_impl() usize { + $if macos { + mut hs := C.vm_statistics64_data_t{} + mut vmsz := u32(C.HOST_VM_INFO64_COUNT) + mut hps := u32(0) + mut host := C.mach_host_self() + unsafe { + C.host_statistics64(host, C.HOST_VM_INFO64, &int(&hs), &vmsz) + C.host_page_size(host, &C.vm_size_t(&hps)) + } + return usize(u64(hs.free_count) * u64(hps)) + } + return 1 +} diff --git a/vlib/runtime/free_memory_impl_default.c.v b/vlib/runtime/free_memory_impl_default.c.v new file mode 100644 index 0000000000..eacb8fff16 --- /dev/null +++ b/vlib/runtime/free_memory_impl_default.c.v @@ -0,0 +1,5 @@ +module runtime + +fn free_memory_impl() usize { + return 1 +} diff --git a/vlib/runtime/free_memory_impl_linux.c.v b/vlib/runtime/free_memory_impl_linux.c.v new file mode 100644 index 0000000000..7344f7c518 --- /dev/null +++ b/vlib/runtime/free_memory_impl_linux.c.v @@ -0,0 +1,10 @@ +module runtime + +fn free_memory_impl() usize { + $if linux { + page_size := usize(C.sysconf(C._SC_PAGESIZE)) + av_phys_pages := usize(C.sysconf(C._SC_AVPHYS_PAGES)) + return page_size * av_phys_pages + } + return 1 +} diff --git a/vlib/runtime/runtime_nix.c.v b/vlib/runtime/runtime_nix.c.v index 1863546b28..96da8aec61 100644 --- a/vlib/runtime/runtime_nix.c.v +++ b/vlib/runtime/runtime_nix.c.v @@ -6,3 +6,15 @@ fn C.sysconf(name int) i64 pub fn nr_cpus() int { return int(C.sysconf(C._SC_NPROCESSORS_ONLN)) } + +// total_memory returns total physical memory found on the system. +pub fn total_memory() usize { + page_size := usize(C.sysconf(C._SC_PAGESIZE)) + phys_pages := usize(C.sysconf(C._SC_PHYS_PAGES)) + return page_size * phys_pages +} + +// free_memory returns free physical memory found on the system. +pub fn free_memory() usize { + return free_memory_impl() +} diff --git a/vlib/runtime/runtime_test.v b/vlib/runtime/runtime_test.v index d1808905c0..347fc5a7fb 100644 --- a/vlib/runtime/runtime_test.v +++ b/vlib/runtime/runtime_test.v @@ -1,32 +1,46 @@ import runtime +fn test_physical_memory() { + total := runtime.total_memory() + free := runtime.free_memory() + println('total memory: ${total}') + println('free memory: ${free}') + assert total > 0 && free > 0 +} + fn test_nr_cpus() { nr_cpus := runtime.nr_cpus() + println(' nr cpus: ${nr_cpus}') assert nr_cpus > 0 } fn test_nr_jobs() { nr_jobs := runtime.nr_jobs() + println(' nr jobs: ${nr_jobs}') assert nr_jobs > 0 } fn test_is_32bit() { x := runtime.is_32bit().str() + println(' is_32bit: ${x}') assert x == 'true' || x == 'false' } fn test_is_64bit() { x := runtime.is_64bit().str() + println(' is_64bit: ${x}') assert x == 'true' || x == 'false' } fn test_is_little_endian() { x := runtime.is_little_endian().str() + println(' is_le: ${x}') assert x == 'true' || x == 'false' } fn test_is_big_endian() { x := runtime.is_big_endian().str() + println(' is_be: ${x}') assert x == 'true' || x == 'false' } diff --git a/vlib/runtime/runtime_windows.c.v b/vlib/runtime/runtime_windows.c.v index de5b2ce5e3..76dfcacc68 100644 --- a/vlib/runtime/runtime_windows.c.v +++ b/vlib/runtime/runtime_windows.c.v @@ -7,7 +7,14 @@ struct C.SYSTEM_INFO { dwNumberOfProcessors u32 } +[typedef] +struct C.MEMORYSTATUS { + dwTotalPhys usize + dwAvailPhys usize +} + fn C.GetSystemInfo(&C.SYSTEM_INFO) +fn C.GlobalMemoryStatus(&C.MEMORYSTATUS) // nr_cpus returns the number of virtual CPU cores found on the system. pub fn nr_cpus() int { @@ -19,3 +26,17 @@ pub fn nr_cpus() int { } return nr } + +// total_memory returns total physical memory found on the system. +pub fn total_memory() usize { + memory_status := C.MEMORYSTATUS{} + C.GlobalMemoryStatus(&memory_status) + return memory_status.dwTotalPhys +} + +// free_memory returns free physical memory found on the system. +pub fn free_memory() usize { + memory_status := C.MEMORYSTATUS{} + C.GlobalMemoryStatus(&memory_status) + return memory_status.dwAvailPhys +}