pax_global_header00006660000000000000000000000064152250603040014507gustar00rootroot0000000000000052 comment=cc711c4e57fbdbc46765195f3c13542f11e5bb15 ocaml-mem_usage-0.2.0/000077500000000000000000000000001522506030400145415ustar00rootroot00000000000000ocaml-mem_usage-0.2.0/.github/000077500000000000000000000000001522506030400161015ustar00rootroot00000000000000ocaml-mem_usage-0.2.0/.github/workflows/000077500000000000000000000000001522506030400201365ustar00rootroot00000000000000ocaml-mem_usage-0.2.0/.github/workflows/main.yml000066400000000000000000000011451522506030400216060ustar00rootroot00000000000000name: CI on: [push] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [macos-latest, ubuntu-24.04, windows-latest] compiler: [4.14.2, 5.2.0] steps: - name: Checkout code uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Build and test module uses: savonet/build-and-test-ocaml-module@681b8ba0c5f5e2e98869bb3672338c65c56e1b24 # main with: ocaml-compiler: ${{ matrix.compiler }} ocaml-mem_usage-0.2.0/.gitignore000066400000000000000000000000161522506030400165260ustar00rootroot00000000000000.*.sw* _build ocaml-mem_usage-0.2.0/CHANGES000066400000000000000000000013241522506030400155340ustar00rootroot000000000000000.1.3 (2026-02-21) ===== * Fix total physical memory on macos. * Fix uninitialized variables on linux. * Use smaps_rollup on linux when available, count Private_Clean for accurate USS. * Windows: add SDK version guard for PROCESS_MEMORY_COUNTERS_EX2, add error handling. 0.1.2 (2025-01-18) ===== * Fixed compilation on freebsd. 0.1.1 (2024-04-17) ===== * Added private and swapped process memory. 0.1.0 (2024-01-31) ====== * Widen memory size integers (#4) * Allow compilation with OCaml 5 (#5) 0.0.4 (2022-06-28) ===== * Fixed buffer overflow using `fscanf` 0.0.3 (2022-04-30) ====== * Fix parsing of proc file on linux. 0.0.2 (2022-04-27) ====== * Fix segfault (#1) 0.0.1 (2022-02-14) ====== * Initial release 💝 ocaml-mem_usage-0.2.0/LICENSE000066400000000000000000000020551522506030400155500ustar00rootroot00000000000000MIT License Copyright (c) 2024 Savonet team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ocaml-mem_usage-0.2.0/README.md000066400000000000000000000045301522506030400160220ustar00rootroot00000000000000> [!WARNING] > This repository is read-only. All changes must be made in > [savonet/liquidsoap](https://github.com/savonet/liquidsoap) under > `src/modules/synced/mem_usage/` and will be mirrored here automatically. # ocaml-mem_usage ![GitHub](https://img.shields.io/github/license/savonet/ocaml-mem_usage) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/savonet/ocaml-mem_usage/.github/workflows/main.yml?branch=main) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/savonet/ocaml-mem_usage) A cross-platform OCaml module for reporting memory usage, with a focus on distinguishing **private memory** (allocated by the process itself) from **shared memory** (e.g., shared libraries, memory-mapped files). # Overview The module reports both system-wide and per-process memory statistics: | Field | Description | | ---------------------------- | ------------------------------------------ | | `total_physical_memory` | Total RAM installed on the system | | `total_virtual_memory` | Total virtual memory (RAM + swap) | | `total_used_physical_memory` | RAM currently in use system-wide | | `total_used_virtual_memory` | Virtual memory in use system-wide | | `process_virtual_memory` | Virtual address space of the process | | `process_physical_memory` | Resident set size (RSS) - pages in RAM | | `process_private_memory` | Private pages unique to this process (USS) | | `process_swapped_memory` | Process pages swapped to disk | The key metric is `process_private_memory` which represents memory that would be freed if this process terminates, excluding shared libraries and other shared mappings. # Supported Platforms - Linux - macOS - Windows - FreeBSD # Example ```ocaml let () = let info = Mem_usage.info () in Printf.printf "Process private memory: %s\n" (Mem_usage.prettify_bytes ~binary:true info.process_private_memory) ``` Output: ``` Process private memory: 1.25 MiB ``` # Installation ``` opam install mem_usage ``` To install from source: ``` git clone https://github.com/savonet/ocaml-mem_usage.git cd ocaml-mem_usage opam install . ``` # Documentation [API documentation](https://www.liquidsoap.info/ocaml-mem_usage/mem_usage/index.html) # License MIT ocaml-mem_usage-0.2.0/dune-project000066400000000000000000000006071522506030400170660ustar00rootroot00000000000000(lang dune 3.23) (version 0.1.3) (name mem_usage) (source (github savonet/ocaml-mem_usage)) (license MIT) (authors "Romain Beauxis ") (maintainers "The Savonet Team ") (generate_opam_files true) (subst disabled) (package (name mem_usage) (allow_empty) (synopsis "Cross-platform stats about memory usage") (depends (ocaml (>= 4.08))) ) ocaml-mem_usage-0.2.0/lib/000077500000000000000000000000001522506030400153075ustar00rootroot00000000000000ocaml-mem_usage-0.2.0/lib/c_flags.freebsd.sexp000066400000000000000000000000311522506030400212110ustar00rootroot00000000000000("-I/usr/local/include") ocaml-mem_usage-0.2.0/lib/c_library_flags.freebsd.sexp000066400000000000000000000000371522506030400227430ustar00rootroot00000000000000("-L/usr/local/lib -lsysinfo") ocaml-mem_usage-0.2.0/lib/c_library_flags.mingw.sexp000066400000000000000000000000141522506030400224450ustar00rootroot00000000000000("-lpsapi") ocaml-mem_usage-0.2.0/lib/c_library_flags.mingw64.sexp000066400000000000000000000000141522506030400226170ustar00rootroot00000000000000("-lpsapi") ocaml-mem_usage-0.2.0/lib/dune000066400000000000000000000007511522506030400161700ustar00rootroot00000000000000(library (name mem_usage) (public_name mem_usage) (synopsis "Cross-platform memory usage information") (foreign_stubs (language c) (names mem_usage) (flags (:standard (:include c_flags.%{system}.sexp)))) (c_library_flags (:include c_library_flags.%{system}.sexp))) (rule (target c_flags.%{system}.sexp) (mode fallback) (action (write-file %{target} "()"))) (rule (target c_library_flags.%{system}.sexp) (mode fallback) (action (write-file %{target} "()"))) ocaml-mem_usage-0.2.0/lib/mem_usage.c000066400000000000000000000256341522506030400174270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2024 Savonet team // // SPDX-License-Identifier: MIT #include #include #include #include #if defined(WIN32) #include #include #include #include // PROCESS_MEMORY_COUNTERS_EX2 requires Windows 10 1607+ / SDK 10.0.14393.0+ #if !defined(PROCESS_MEMORY_COUNTERS_EX2) typedef struct _PROCESS_MEMORY_COUNTERS_EX2 { DWORD cb; DWORD PageFaultCount; SIZE_T PeakWorkingSetSize; SIZE_T WorkingSetSize; SIZE_T QuotaPeakPagedPoolUsage; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaPeakNonPagedPoolUsage; SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; SIZE_T PrivateUsage; SIZE_T PrivateWorkingSetSize; ULONG64 SharedCommitUsage; } PROCESS_MEMORY_COUNTERS_EX2; #endif CAMLprim value ocaml_mem_usage_mem_usage(value unit) { CAMLparam0(); CAMLlocal1(ret); MEMORYSTATUSEX mem_info; PROCESS_MEMORY_COUNTERS_EX2 pmc; DWORDLONG total_virtual_memory = 0; DWORDLONG total_used_virtual_memory = 0; DWORDLONG total_physical_memory = 0; DWORDLONG total_used_physical_memory = 0; SIZE_T process_virtual_memory = 0; SIZE_T process_physical_memory = 0; SIZE_T process_private_memory = 0; SIZE_T process_swapped_memory = 0; caml_release_runtime_system(); mem_info.dwLength = sizeof(MEMORYSTATUSEX); if (GlobalMemoryStatusEx(&mem_info)) { total_virtual_memory = mem_info.ullTotalPageFile; total_used_virtual_memory = mem_info.ullTotalPageFile - mem_info.ullAvailPageFile; total_physical_memory = mem_info.ullTotalPhys; total_used_physical_memory = mem_info.ullTotalPhys - mem_info.ullAvailPhys; } pmc.cb = sizeof(pmc); if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc))) { process_virtual_memory = pmc.PrivateUsage; process_physical_memory = pmc.WorkingSetSize; process_private_memory = pmc.PrivateWorkingSetSize; // Private committed memory not resident in the working set: the closest // per-process approximation of paged-out memory available here. if (pmc.PrivateUsage > pmc.PrivateWorkingSetSize) process_swapped_memory = pmc.PrivateUsage - pmc.PrivateWorkingSetSize; } else { // Older Windows rejects the EX2 size: retry with the EX layout. PROCESS_MEMORY_COUNTERS_EX pmc_ex; pmc_ex.cb = sizeof(pmc_ex); if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS *)&pmc_ex, sizeof(pmc_ex))) { process_virtual_memory = pmc_ex.PrivateUsage; process_physical_memory = pmc_ex.WorkingSetSize; if (pmc_ex.PrivateUsage > pmc_ex.WorkingSetSize) process_swapped_memory = pmc_ex.PrivateUsage - pmc_ex.WorkingSetSize; } } caml_acquire_runtime_system(); ret = caml_alloc_tuple(8); Store_field(ret, 0, Val_long(total_virtual_memory)); Store_field(ret, 1, Val_long(total_physical_memory)); Store_field(ret, 2, Val_long(total_used_virtual_memory)); Store_field(ret, 3, Val_long(total_used_physical_memory)); Store_field(ret, 4, Val_long(process_virtual_memory)); Store_field(ret, 5, Val_long(process_physical_memory)); Store_field(ret, 6, Val_long(process_private_memory)); Store_field(ret, 7, Val_long(process_swapped_memory)); CAMLreturn(ret); } #elif defined(__APPLE__) #include #include #include #include #include #include #include #include #include void private_pages(unsigned int *pages_resident, unsigned int *pages_swapped_out) { mach_vm_address_t address = 0; mach_vm_size_t size = 0; uint32_t depth; vm_region_submap_info_data_64_t info; mach_msg_type_number_t count; kern_return_t kr; *pages_resident = 0; *pages_swapped_out = 0; while (1) { depth = 2048; count = VM_REGION_SUBMAP_INFO_COUNT_64; kr = mach_vm_region_recurse(mach_task_self(), &address, &size, &depth, (vm_region_recurse_info_t)&info, &count); if (kr != KERN_SUCCESS) break; if (info.share_mode == SM_PRIVATE) { *pages_resident += info.pages_resident; *pages_swapped_out += info.pages_swapped_out; } address += size; } } CAMLprim value ocaml_mem_usage_mem_usage(value unit) { CAMLparam0(); CAMLlocal1(ret); uint64_t total_virtual_memory, total_physical_memory, total_used_physical_memory, total_used_virtual_memory, process_physical_memory, process_virtual_memory, process_private_memory, process_swapped_memory; struct xsw_usage vmem_usage = {0}; size_t size = sizeof(vmem_usage); mach_task_basic_info_data_t t_info; mach_msg_type_number_t t_info_count = MACH_TASK_BASIC_INFO_COUNT; vm_size_t page_size; mach_port_t mach_port; mach_msg_type_number_t count; vm_statistics64_data_t vm_stats; int pagesize; unsigned int pages_resident, pages_swapped_out; caml_release_runtime_system(); if (sysctlbyname("vm.swapusage", &vmem_usage, &size, NULL, 0) != 0) { fprintf(stderr, "Error while getting swap usage.\n"); vmem_usage.xsu_total = 0; vmem_usage.xsu_used = 0; } if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count)) { fprintf(stderr, "Unable to get virtual memory currently used by the process.\n"); process_physical_memory = 0; process_virtual_memory = 0; } else { process_physical_memory = t_info.resident_size; process_virtual_memory = t_info.virtual_size; } // hw.memsize is uint64_t, hw.physmem is 32-bit and overflows >2GB { uint64_t memsize; size_t memsize_len = sizeof(memsize); if (sysctlbyname("hw.memsize", &memsize, &memsize_len, NULL, 0) != 0) { fprintf(stderr, "Unable to get total physical memory.\n"); total_physical_memory = 0; } else { total_physical_memory = memsize; } } mach_port = mach_host_self(); count = HOST_VM_INFO64_COUNT; if (host_page_size(mach_port, &page_size) != KERN_SUCCESS) { fprintf(stderr, "Unable to get host page size.\n"); total_used_physical_memory = 0; } else { if (host_statistics64(mach_port, HOST_VM_INFO64, (host_info64_t)&vm_stats, &count) != KERN_SUCCESS) { fprintf(stderr, "Unable to get host stats.\n"); total_used_physical_memory = 0; } else { // Matches Activity Monitor's notion of used memory: anonymous/active // pages + wired + compressed. Inactive pages are mostly reclaimable // file cache and are not counted. total_used_physical_memory = ((uint64_t)vm_stats.active_count + (uint64_t)vm_stats.wire_count + (uint64_t)vm_stats.compressor_page_count) * (uint64_t)page_size; } } mach_port_deallocate(mach_task_self(), mach_port); // RAM + swap, matching the Linux implementation's semantics. total_virtual_memory = total_physical_memory + vmem_usage.xsu_total; total_used_virtual_memory = total_used_physical_memory + vmem_usage.xsu_used; pagesize = getpagesize(); private_pages(&pages_resident, &pages_swapped_out); process_private_memory = (uint64_t)pages_resident * pagesize; process_swapped_memory = (uint64_t)pages_swapped_out * pagesize; caml_acquire_runtime_system(); ret = caml_alloc_tuple(8); Store_field(ret, 0, Val_long(total_virtual_memory)); Store_field(ret, 1, Val_long(total_physical_memory)); Store_field(ret, 2, Val_long(total_used_virtual_memory)); Store_field(ret, 3, Val_long(total_used_physical_memory)); Store_field(ret, 4, Val_long(process_virtual_memory)); Store_field(ret, 5, Val_long(process_physical_memory)); Store_field(ret, 6, Val_long(process_private_memory)); Store_field(ret, 7, Val_long(process_swapped_memory)); CAMLreturn(ret); } #else #include #include #include #include #include CAMLprim value ocaml_mem_usage_mem_usage(value unit) { CAMLparam0(); CAMLlocal1(ret); struct sysinfo memInfo; uint64_t total_virtual_memory, total_physical_memory, total_used_virtual_memory, total_used_physical_memory; unsigned long long process_virtual_memory = 0, process_physical_memory = 0, process_private_memory = 0, process_swapped_memory = 0, tmp; FILE *file; char buffer[1024] = ""; caml_release_runtime_system(); sysinfo(&memInfo); total_physical_memory = memInfo.totalram; total_physical_memory *= memInfo.mem_unit; total_virtual_memory = memInfo.totalram; total_virtual_memory += memInfo.totalswap; total_virtual_memory *= memInfo.mem_unit; // bufferram is reclaimable cache; sysinfo does not expose the page cache, // so this still over-reports "used" compared to /proc/meminfo MemAvailable. total_used_physical_memory = memInfo.totalram - memInfo.freeram - memInfo.bufferram; total_used_physical_memory *= memInfo.mem_unit; total_used_virtual_memory = memInfo.totalram - memInfo.freeram - memInfo.bufferram; total_used_virtual_memory += memInfo.totalswap - memInfo.freeswap; total_used_virtual_memory *= memInfo.mem_unit; file = fopen("/proc/self/status", "r"); if (file) { while (fscanf(file, " %1023s", buffer) == 1) { if (strcmp(buffer, "VmSize:") == 0) { if (fscanf(file, " %llu", &process_virtual_memory) != 1) process_virtual_memory = 0; process_virtual_memory *= 1024; continue; } if (strcmp(buffer, "VmRSS:") == 0) { if (fscanf(file, " %llu", &process_physical_memory) != 1) process_physical_memory = 0; process_physical_memory *= 1024; continue; } } fclose(file); } // smaps_rollup (Linux 4.14+) provides aggregated stats in one entry // Falls back to smaps for older kernels file = fopen("/proc/self/smaps_rollup", "r"); if (!file) file = fopen("/proc/self/smaps", "r"); if (file) { while (fscanf(file, " %1023s", buffer) == 1) { if (strcmp(buffer, "Private_Dirty:") == 0 || strcmp(buffer, "Private_Clean:") == 0) { if (fscanf(file, " %llu", &tmp) == 1) process_private_memory += tmp * 1024; continue; } if (strcmp(buffer, "Swap:") == 0) { if (fscanf(file, " %llu", &tmp) == 1) process_swapped_memory += tmp * 1024; continue; } } fclose(file); } caml_acquire_runtime_system(); ret = caml_alloc_tuple(8); Store_field(ret, 0, Val_long(total_virtual_memory)); Store_field(ret, 1, Val_long(total_physical_memory)); Store_field(ret, 2, Val_long(total_used_virtual_memory)); Store_field(ret, 3, Val_long(total_used_physical_memory)); Store_field(ret, 4, Val_long(process_virtual_memory)); Store_field(ret, 5, Val_long(process_physical_memory)); Store_field(ret, 6, Val_long(process_private_memory)); Store_field(ret, 7, Val_long(process_swapped_memory)); CAMLreturn(ret); } #endif ocaml-mem_usage-0.2.0/lib/mem_usage.ml000066400000000000000000000033211522506030400176020ustar00rootroot00000000000000(* * SPDX-FileCopyrightText: 2022 - 2024 Savonet team * * SPDX-License-Identifier: MIT *) type t = { total_virtual_memory : int; total_physical_memory : int; total_used_virtual_memory : int; total_used_physical_memory : int; process_virtual_memory : int; process_physical_memory : int; process_private_memory : int; process_swapped_memory : int; } external info : unit -> t = "ocaml_mem_usage_mem_usage" let byte_units = ["B"; "kB"; "MB"; "GB"; "TB"; "PB"; "EB"; "ZB"; "YB"] let bibyte_units = ["B"; "kiB"; "MiB"; "GiB"; "TiB"; "PiB"; "EiB"; "ZiB"; "YiB"] let bit_units = ["b"; "kbit"; "Mbit"; "Gbit"; "Tbit"; "Pbit"; "Ebit"; "Zbit"; "Ybit"] let bibit_units = ["b"; "kibit"; "Mibit"; "Gibit"; "Tibit"; "Pibit"; "Eibit"; "Zibit"; "Yibit"] let prettify_bytes ?(float_printer = Printf.sprintf "%.02f") ?(signed = false) ?(bits = false) ?(binary = false) bytes = let units = match (bits, binary) with | true, true -> bibit_units | true, false -> bit_units | false, true -> bibyte_units | false, false -> byte_units in let prefix, bytes = if bytes < 0 then ("-", -bytes) else ((if signed then "+" else ""), bytes) in if bytes = 0 then Printf.sprintf "%s0 %s" prefix (List.hd units) else ( let exponent = Float.floor (if binary then log (float bytes) /. log 1024. else log10 (float bytes) /. 3.) in let unit_index = if List.length units - 1 < int_of_float exponent then List.length units - 1 else int_of_float exponent in let bytes = float bytes /. Float.pow (if binary then 1024. else 1000.) exponent in Printf.sprintf "%s%s %s" prefix (float_printer bytes) (List.nth units unit_index)) ocaml-mem_usage-0.2.0/lib/mem_usage.mli000066400000000000000000000026131522506030400177560ustar00rootroot00000000000000(* * SPDX-FileCopyrightText: 2022 - 2024 Savonet team * * SPDX-License-Identifier: MIT *) (** All values are in bytes. - [total_virtual_memory]: RAM + swap on Linux and macOS, commit limit (RAM + page files) on Windows. - [total_used_virtual_memory]: used RAM + used swap (used commit charge on Windows). - [total_used_physical_memory]: used RAM. Excludes easily reclaimable cache where the platform exposes it (buffers on Linux, inactive pages on macOS). - [process_virtual_memory]: process address-space usage (committed private bytes on Windows). - [process_physical_memory]: process resident set / working set. - [process_private_memory]: resident memory private to the process. - [process_swapped_memory]: process memory currently swapped out (approximated on Windows by committed-but-non-resident private bytes). On FreeBSD the [process_*] fields are always [0]: they are read from Linux-specific procfs files. *) type t = { total_virtual_memory : int; total_physical_memory : int; total_used_virtual_memory : int; total_used_physical_memory : int; process_virtual_memory : int; process_physical_memory : int; process_private_memory : int; process_swapped_memory : int; } val info : unit -> t val prettify_bytes : ?float_printer:(float -> string) -> ?signed:bool -> ?bits:bool -> ?binary:bool -> int -> string ocaml-mem_usage-0.2.0/mem_usage.opam000066400000000000000000000013501522506030400173600ustar00rootroot00000000000000# This file is generated by dune, edit dune-project instead opam-version: "2.0" version: "0.1.3" synopsis: "Cross-platform stats about memory usage" maintainer: ["The Savonet Team "] authors: ["Romain Beauxis "] license: "MIT" homepage: "https://github.com/savonet/ocaml-mem_usage" bug-reports: "https://github.com/savonet/ocaml-mem_usage/issues" build: [ [ "dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} "@doc" {with-doc} ] ] dev-repo: "git+https://github.com/savonet/ocaml-mem_usage.git" x-maintenance-intent: ["(latest)"] depends: [ "conf-sysinfo" {os = "freebsd"} "ocaml" {>= "4.08"} "dune" {>= "3.23"} "odoc" {with-doc} ] ocaml-mem_usage-0.2.0/mem_usage.opam.template000066400000000000000000000001561522506030400211750ustar00rootroot00000000000000depends: [ "conf-sysinfo" {os = "freebsd"} "ocaml" {>= "4.08"} "dune" {>= "3.23"} "odoc" {with-doc} ] ocaml-mem_usage-0.2.0/test/000077500000000000000000000000001522506030400155205ustar00rootroot00000000000000ocaml-mem_usage-0.2.0/test/dune000066400000000000000000000000531522506030400163740ustar00rootroot00000000000000(test (name test) (libraries mem_usage)) ocaml-mem_usage-0.2.0/test/test.ml000066400000000000000000000022271522506030400170340ustar00rootroot00000000000000(* * SPDX-FileCopyrightText: 2022 - 2024 Savonet team * * SPDX-License-Identifier: MIT *) let () = let { Mem_usage.total_virtual_memory; total_physical_memory; total_used_virtual_memory; total_used_physical_memory; process_virtual_memory; process_physical_memory; process_private_memory; process_swapped_memory; } = Mem_usage.info () in Printf.printf {| Total virtual memory: %s Total physical memory: %s Used virtual memory: %s Used physical memory: %s Process virtual memory: %s Process physical memory: %s Process private memory: %s Process swapped memory: %s |} (Mem_usage.prettify_bytes ~binary:true total_virtual_memory) (Mem_usage.prettify_bytes ~binary:true total_physical_memory) (Mem_usage.prettify_bytes ~binary:true total_used_virtual_memory) (Mem_usage.prettify_bytes ~binary:true total_used_physical_memory) (Mem_usage.prettify_bytes ~binary:true process_virtual_memory) (Mem_usage.prettify_bytes ~binary:true process_physical_memory) (Mem_usage.prettify_bytes ~binary:true process_private_memory) (Mem_usage.prettify_bytes ~binary:true process_swapped_memory)