Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,8 @@
|
||||
## Description
|
||||
|
||||
`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.
|
||||
@@ -0,0 +1,63 @@
|
||||
module runtime
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
|
||||
@[typedef]
|
||||
pub struct C.vm_size_t {
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.vm_statistics64_data_t {
|
||||
free_count u32
|
||||
purgeable_count u32
|
||||
speculative_count u32
|
||||
external_page_count u32
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.host_t {}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.task_t {}
|
||||
|
||||
fn C.mach_host_self() C.host_t
|
||||
fn C.mach_task_self() C.task_t
|
||||
fn C.mach_port_deallocate(task C.task_t, host C.host_t) i32
|
||||
fn C.host_page_size(host C.host_t, out_page_size &C.vm_size_t) i32
|
||||
fn C.host_statistics64(host C.host_t, flavor i32, host_info_out &int, host_info_outCnt &u32) i32
|
||||
|
||||
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()
|
||||
defer {
|
||||
// Critical: Release send right for host port
|
||||
// --------------------------------------------------
|
||||
// Mach ports are system resources. Calling mach_host_self()
|
||||
// increments the port's reference count. We must manually release
|
||||
// to prevent resource leaks (port exhaustion can cause kernel failures).
|
||||
// mach_port_deallocate decrements the reference count, allowing
|
||||
// system resource reclamation when count reaches zero.
|
||||
// Parameters:
|
||||
// C.mach_task_self() - Port for current task
|
||||
// host - Host port to release
|
||||
// Return value ignored (_) since we only care about resource cleanup
|
||||
_ := C.mach_port_deallocate(C.mach_task_self(), host)
|
||||
}
|
||||
unsafe {
|
||||
retval_1 := C.host_statistics64(host, C.HOST_VM_INFO64, &int(&hs), &vmsz)
|
||||
if retval_1 != C.KERN_SUCCESS {
|
||||
return error('free_memory: `C.host_statistics64()` return = ${retval_1}')
|
||||
}
|
||||
retval_2 := C.host_page_size(host, &C.vm_size_t(&hps))
|
||||
if retval_2 != C.KERN_SUCCESS {
|
||||
return error('free_memory: `C.host_page_size()` return = ${retval_2}')
|
||||
}
|
||||
}
|
||||
return usize(u64(hs.free_count) * u64(hps))
|
||||
}
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module runtime
|
||||
|
||||
fn free_memory_impl() !usize {
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
module runtime
|
||||
|
||||
fn C.sysctlnametomib(name charptr, mib &int, len &usize) i32
|
||||
|
||||
fn free_memory_impl() !usize {
|
||||
$if cross ? {
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
$if !cross ? {
|
||||
$if freebsd {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('free_memory: `C.sysconf()` return error code = ${c_errno_1}')
|
||||
}
|
||||
mut mib := [4]int{}
|
||||
mut len := usize(4)
|
||||
retval_2 := unsafe {
|
||||
C.sysctlnametomib(c'vm.stats.vm.v_free_count', &mib[0], &len)
|
||||
}
|
||||
c_errno_2 := C.errno
|
||||
if retval_2 == -1 {
|
||||
return error('free_memory: `C.sysctlnametomib()` return error code = ${c_errno_2}')
|
||||
}
|
||||
mut free_pages := int(0)
|
||||
bufsize := usize(4)
|
||||
retval_3 := unsafe {
|
||||
C.sysctl(&mib[0], mib.len, &free_pages, &bufsize, 0, 0)
|
||||
}
|
||||
c_errno_3 := C.errno
|
||||
if retval_3 == -1 {
|
||||
return error('free_memory: `C.sysctl()` return error code = ${c_errno_3}')
|
||||
}
|
||||
return page_size * usize(free_pages)
|
||||
}
|
||||
}
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
module runtime
|
||||
|
||||
fn free_memory_impl() !usize {
|
||||
$if cross ? {
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
$if !cross ? {
|
||||
$if linux {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('free_memory: `C.sysconf(C._SC_PAGESIZE)` return error code = ${c_errno_1}')
|
||||
}
|
||||
av_phys_pages := usize(C.sysconf(C._SC_AVPHYS_PAGES))
|
||||
c_errno_2 := C.errno
|
||||
if av_phys_pages == usize(-1) {
|
||||
return error('free_memory: `C.sysconf(C._SC_AVPHYS_PAGES)` return error code = ${c_errno_2}')
|
||||
}
|
||||
return page_size * av_phys_pages
|
||||
}
|
||||
}
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
module runtime
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <uvm/uvmexp.h>
|
||||
|
||||
struct C.uvmexp {
|
||||
pagesize int
|
||||
free int
|
||||
}
|
||||
|
||||
fn free_memory_impl() !usize {
|
||||
$if cross ? {
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
$if !cross ? {
|
||||
$if openbsd {
|
||||
mib := [C.CTL_VM, C.VM_UVMEXP]!
|
||||
mut uvm := C.uvmexp{0, 0}
|
||||
mut len := usize(sizeof(C.uvmexp))
|
||||
retval := unsafe { C.sysctl(&mib[0], mib.len, &uvm, &len, C.NULL, 0) }
|
||||
c_errno := C.errno
|
||||
if retval == -1 {
|
||||
return error('free_memory: `C.sysctl()` return error code = ${c_errno}')
|
||||
}
|
||||
return usize(uvm.pagesize) * usize(uvm.free)
|
||||
}
|
||||
}
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
module runtime
|
||||
|
||||
import os
|
||||
|
||||
// nr_jobs returns the same as `nr_cpus`, but influenced by the env variable `VJOBS`.
|
||||
// If the environment variable `VJOBS` is set, and has a value > 0,
|
||||
// then `nr_jobs` will return that number instead.
|
||||
// This is useful for runtime tweaking of e.g. threaded or concurrent code.
|
||||
pub fn nr_jobs() int {
|
||||
$if cross ? {
|
||||
// A single thread is *more likely* to work consistently everywhere during bootstrapping.
|
||||
// NB: the compiler itself uses runtime.nr_jobs() and sync.pool to process things in parallel
|
||||
// in its cgen stage. Returning 1 here, increases the chances of it working on non linux systems.
|
||||
return 1
|
||||
}
|
||||
mut cpus := nr_cpus()
|
||||
// allow for overrides, for example using `VJOBS=32 ./v test .`
|
||||
vjobs := os.getenv('VJOBS').int()
|
||||
if vjobs > 0 {
|
||||
cpus = vjobs
|
||||
}
|
||||
if cpus == 0 {
|
||||
return 1
|
||||
}
|
||||
return cpus
|
||||
}
|
||||
|
||||
// is_32bit returns true if the current executable is running on a 32 bit system.
|
||||
pub fn is_32bit() bool {
|
||||
$if x32 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// is_64bit returns true if the current executable is running on a 64 bit system.
|
||||
pub fn is_64bit() bool {
|
||||
$if x64 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// is_little_endian returns true if the current executable is running on a little-endian system.
|
||||
pub fn is_little_endian() bool {
|
||||
$if little_endian {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// is_big_endian returns true if the current executable is running on a big-endian system.
|
||||
pub fn is_big_endian() bool {
|
||||
$if big_endian {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
module runtime
|
||||
|
||||
fn C.sysconf(name i32) i64
|
||||
|
||||
// nr_cpus returns the number of virtual CPU cores found on the system.
|
||||
pub fn nr_cpus() int {
|
||||
mut cpus := int(C.sysconf(C._SC_NPROCESSORS_ONLN))
|
||||
if cpus < 1 {
|
||||
eprintln('Warning: sysconf(_SC_NPROCESSORS_ONLN) returned -1, returning CPU count as 1')
|
||||
cpus = 1
|
||||
}
|
||||
return cpus
|
||||
}
|
||||
|
||||
// total_memory returns total physical memory found on the system.
|
||||
pub fn total_memory() !usize {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('total_memory: `C.sysconf(C._SC_PAGESIZE)` return error code = ${c_errno_1}')
|
||||
}
|
||||
phys_pages := usize(C.sysconf(C._SC_PHYS_PAGES))
|
||||
c_errno_2 := C.errno
|
||||
if phys_pages == usize(-1) {
|
||||
return error('total_memory: `C.sysconf(C._SC_PHYS_PAGES)` return error code = ${c_errno_2}')
|
||||
}
|
||||
return page_size * phys_pages
|
||||
}
|
||||
|
||||
// free_memory returns free physical memory found on the system.
|
||||
// Note: implementation available only on Darwin, FreeBSD, Linux, OpenBSD and
|
||||
// Windows. Otherwise, returns 'free_memory: not implemented'.
|
||||
pub fn free_memory() !usize {
|
||||
return free_memory_impl()!
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import os
|
||||
import runtime
|
||||
|
||||
fn test_physical_memory() {
|
||||
$if windows || linux || darwin || freebsd || openbsd {
|
||||
total := runtime.total_memory()!
|
||||
free := runtime.free_memory()!
|
||||
println('total memory: ${total}')
|
||||
println('free memory: ${free}')
|
||||
assert total > 0 && free > 0
|
||||
} $else {
|
||||
total := runtime.total_memory()!
|
||||
_ := runtime.free_memory() or { assert err.msg().contains('not implemented') }
|
||||
assert total > 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_nr_jobs_matches_nr_cpus_without_vjobs() {
|
||||
env := os.environ()
|
||||
had_vjobs := 'VJOBS' in env
|
||||
saved_vjobs := env['VJOBS']
|
||||
defer {
|
||||
if had_vjobs {
|
||||
os.setenv('VJOBS', saved_vjobs, true)
|
||||
} else {
|
||||
os.unsetenv('VJOBS')
|
||||
}
|
||||
}
|
||||
os.unsetenv('VJOBS')
|
||||
assert runtime.nr_jobs() == runtime.nr_cpus()
|
||||
}
|
||||
|
||||
fn test_nr_jobs_uses_vjobs_override() {
|
||||
env := os.environ()
|
||||
had_vjobs := 'VJOBS' in env
|
||||
saved_vjobs := env['VJOBS']
|
||||
defer {
|
||||
if had_vjobs {
|
||||
os.setenv('VJOBS', saved_vjobs, true)
|
||||
} else {
|
||||
os.unsetenv('VJOBS')
|
||||
}
|
||||
}
|
||||
expected_jobs := runtime.nr_cpus() + 1
|
||||
os.setenv('VJOBS', expected_jobs.str(), true)
|
||||
assert runtime.nr_jobs() == expected_jobs
|
||||
}
|
||||
|
||||
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'
|
||||
}
|
||||
|
||||
fn test_is_big_endian_different_than_is_little_endian() {
|
||||
assert runtime.is_big_endian() != runtime.is_little_endian()
|
||||
}
|
||||
|
||||
fn test_is_32bit_different_than_is_64bit() {
|
||||
assert runtime.is_32bit() != runtime.is_64bit()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
module runtime
|
||||
|
||||
import os
|
||||
|
||||
@[typedef]
|
||||
pub struct C.MEMORYSTATUS {
|
||||
dwTotalPhys usize
|
||||
dwAvailPhys usize
|
||||
}
|
||||
|
||||
fn C.GlobalMemoryStatus(&C.MEMORYSTATUS)
|
||||
|
||||
// nr_cpus returns the number of virtual CPU cores found on the system.
|
||||
pub fn nr_cpus() int {
|
||||
sinfo := C.SYSTEM_INFO{}
|
||||
C.GetSystemInfo(&sinfo)
|
||||
mut nr := int(sinfo.dwNumberOfProcessors)
|
||||
if nr == 0 {
|
||||
nr = os.getenv('NUMBER_OF_PROCESSORS').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
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
module runtime
|
||||
|
||||
struct C.task_basic_info {
|
||||
resident_size u64
|
||||
}
|
||||
|
||||
fn C.task_info(C.task_t, i32, &C.task_basic_info, &u64) i32
|
||||
|
||||
// used_memory retrieves the current physical memory usage of the process.
|
||||
pub fn used_memory() !u64 {
|
||||
mut info := C.task_basic_info{}
|
||||
mut count := u64(C.MACH_TASK_BASIC_INFO_COUNT)
|
||||
if C.task_info(C.mach_task_self(), C.TASK_BASIC_INFO, &info, &count) == C.KERN_SUCCESS {
|
||||
return info.resident_size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
module runtime
|
||||
|
||||
// used_memory retrieves the current physical memory usage of the process.
|
||||
// Note: implementation available only on FreeBSD, macOS, Linux, OpenBSD and
|
||||
// Windows. Otherwise, returns 'used_memory: not implemented'.
|
||||
pub fn used_memory() !u64 {
|
||||
return error('used_memory: not implemented')
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
module runtime
|
||||
|
||||
import os
|
||||
|
||||
$if tinyc {
|
||||
#include <sys/resource.h>
|
||||
}
|
||||
struct C.rusage {
|
||||
ru_maxrss int
|
||||
ru_idrss int
|
||||
}
|
||||
|
||||
fn C.getrusage(who i32, usage &C.rusage) i32
|
||||
|
||||
$if !tinyc {
|
||||
#flag -lprocstat
|
||||
|
||||
#include <sys/user.h>
|
||||
#include <libprocstat.h>
|
||||
}
|
||||
struct C.procstat {}
|
||||
|
||||
struct C.kinfo_proc {
|
||||
ki_rssize u64
|
||||
}
|
||||
|
||||
fn C.procstat_open_sysctl() &C.procstat
|
||||
fn C.procstat_close(&C.procstat)
|
||||
fn C.procstat_getprocs(&C.procstat, i32, i32, &u32) &C.kinfo_proc
|
||||
|
||||
// used_memory retrieves the current physical memory usage of the process.
|
||||
pub fn used_memory() !u64 {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('used_memory: C.sysconf() return error code = ${c_errno_1}')
|
||||
}
|
||||
$if tinyc {
|
||||
mut usage := C.rusage{}
|
||||
x := C.getrusage(0, &usage)
|
||||
if x == -1 {
|
||||
c_errno_2 := C.errno
|
||||
return error('used_memory: C.getrusage() return error code = ${c_errno_2}')
|
||||
}
|
||||
return u64(int_max(1, usage.ru_maxrss)) * 1024
|
||||
} $else {
|
||||
mut proc_status := C.procstat_open_sysctl()
|
||||
defer {
|
||||
C.procstat_close(proc_status)
|
||||
}
|
||||
|
||||
mut count := u32(0)
|
||||
|
||||
kip := C.procstat_getprocs(proc_status, C.KERN_PROC_PID | C.KERN_PROC_INC_THREAD,
|
||||
os.getpid(), &count)
|
||||
|
||||
if kip != 0 {
|
||||
return u64(kip.ki_rssize * page_size)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
module runtime
|
||||
|
||||
import os
|
||||
|
||||
// used_memory retrieves the current physical memory usage of the process.
|
||||
@[manualfree]
|
||||
pub fn used_memory() !u64 {
|
||||
buffer := [1024]u8{}
|
||||
pc := unsafe { &buffer[0] }
|
||||
// see https://man7.org/linux/man-pages/man5/proc_pid_stat.5.html for a detailed description of the format.
|
||||
// Here is an example:
|
||||
// 699989 (test_program) R 178038 699989 178038 34816 699989 0 102 0 0 0 0 0 0 0 20 0 1 0 84188763 5726208 129 18446744073709551615 93824992239616 93824992257073 140737488345056 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 93824992275088 93824992276672 93824992280576 140737488346201 140737488346221 140737488346221 140737488351211 0
|
||||
// => read the file in the fixed buffer, search to after the `)` to skip the variable name part, then scan till the `129` RSS value, and then convert it from pages to bytes.
|
||||
mut f := os.open_file('/proc/self/stat', 'r')!
|
||||
defer { f.close() }
|
||||
read := f.read_into_ptr(pc, buffer.len)!
|
||||
if read <= 0 {
|
||||
return error('could not read from /proc/self/stat')
|
||||
}
|
||||
mut c := 0
|
||||
unsafe {
|
||||
// scan to after the process name (`comm`) field:
|
||||
for c < buffer.len && *pc != `)` {
|
||||
pc++
|
||||
c++
|
||||
}
|
||||
mut spaces := 0
|
||||
// the following fields, are space separated numbers, skip past them to the `rss` field:
|
||||
for c < buffer.len && spaces < 22 {
|
||||
if *pc == ` ` {
|
||||
spaces++
|
||||
}
|
||||
pc++
|
||||
c++
|
||||
}
|
||||
mut ndigits := 0
|
||||
// scan till the end of the `rss` field:
|
||||
for c < buffer.len && *(pc + ndigits) != ` ` {
|
||||
ndigits++
|
||||
c++
|
||||
}
|
||||
rss_pages := pc.vstring_with_len(ndigits).u64()
|
||||
page_size := C.sysconf(C._SC_PAGESIZE)
|
||||
return u64(rss_pages * page_size)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
module runtime
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
struct C.rusage {
|
||||
ru_maxrss int
|
||||
}
|
||||
|
||||
fn C.getrusage(who i32, usage &C.rusage) i32
|
||||
|
||||
// used_memory retrieves the current physical memory usage of the process.
|
||||
pub fn used_memory() !u64 {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('used_memory: C.sysconf() return error code = ${c_errno_1}')
|
||||
}
|
||||
|
||||
mut usage := C.rusage{}
|
||||
ret := C.getrusage(C.RUSAGE_SELF, &usage)
|
||||
if ret == -1 {
|
||||
c_errno_2 := C.errno
|
||||
return error('used_memory: C.getrusage() return error code = ${c_errno_2}')
|
||||
}
|
||||
return u64(int_max(1, usage.ru_maxrss)) * 1024
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import runtime
|
||||
|
||||
fn test_used_memory() {
|
||||
used1 := runtime.used_memory()!
|
||||
println('used memory 1 : ${used1}')
|
||||
|
||||
mut mem1 := unsafe { malloc(8 * 1024 * 1024) }
|
||||
unsafe { vmemset(mem1, 1, 8 * 1024 * 1024) }
|
||||
used2 := runtime.used_memory()!
|
||||
println('used memory 2 : ${used2}')
|
||||
|
||||
mut mem2 := unsafe { malloc(64 * 1024 * 1024) }
|
||||
unsafe { vmemset(mem2, 1, 64 * 1024 * 1024) }
|
||||
used3 := runtime.used_memory()!
|
||||
println('used memory 3 : ${used3}')
|
||||
|
||||
assert used1 > 0
|
||||
assert used2 >= used1
|
||||
assert used3 > used2
|
||||
unsafe {
|
||||
println(*&u8(mem1 + 1024))
|
||||
println(*&u8(mem2 + 1024))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
module runtime
|
||||
|
||||
#define PSAPI_VERSION 2
|
||||
#include <psapi.h>
|
||||
|
||||
// Windows 7+ exports K32GetProcessMemoryInfo from kernel32.dll, so avoid
|
||||
// depending on psapi.lib during bootstrap builds.
|
||||
@[typedef]
|
||||
struct C.PROCESS_MEMORY_COUNTERS {
|
||||
cb u32
|
||||
PageFaultCount u32
|
||||
PeakWorkingSetSize usize
|
||||
WorkingSetSize usize
|
||||
QuotaPeakPagedPoolUsage usize
|
||||
QuotaPagedPoolUsage usize
|
||||
QuotaPeakNonPagedPoolUsage usize
|
||||
QuotaNonPagedPoolUsage usize
|
||||
PagefileUsage usize
|
||||
PeakPagefileUsage usize
|
||||
}
|
||||
|
||||
fn C.K32GetProcessMemoryInfo(voidptr, &C.PROCESS_MEMORY_COUNTERS, u32) bool
|
||||
|
||||
// used_memory retrieves the current physical memory usage of the process.
|
||||
pub fn used_memory() !u64 {
|
||||
mut pmc := C.PROCESS_MEMORY_COUNTERS{}
|
||||
pmc.cb = u32(sizeof(pmc))
|
||||
if C.K32GetProcessMemoryInfo(C.GetCurrentProcess(), &pmc, pmc.cb) {
|
||||
return u64(pmc.WorkingSetSize)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Reference in new issue
Block a user