Mercurial > octave
changeset 28372:2f571bfff344
Add "memory" function (patch #9924).
* scripts/miscellaneous/memory.m: Add function that returns memory information
on Linux and Windows platforms.
* scripts/miscellaneous/module.mk: Include new file in build system.
* doc/interpreter/system.txi: Include function documentation in manual.
* scripts/help/__unimplemented__.m: Remove from list.
* NEWS: Add to list of new functions.
author | Lars Kindermann <lars.kindermann@reglos.de> |
---|---|
date | Sat, 02 May 2020 20:18:10 +0200 |
parents | 401599248e4d |
children | 29c655998ac3 |
files | NEWS doc/interpreter/system.txi scripts/help/__unimplemented__.m scripts/miscellaneous/memory.m scripts/miscellaneous/module.mk |
diffstat | 5 files changed, 214 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Wed Apr 22 16:04:48 2020 +0200 +++ b/NEWS Sat May 02 20:18:10 2020 +0200 @@ -101,6 +101,7 @@ * `getpixelposition` * `endsWith` +* `memory` * `rng` * `startsWith`
--- a/doc/interpreter/system.txi Wed Apr 22 16:04:48 2020 +0200 +++ b/doc/interpreter/system.txi Sat May 02 20:18:10 2020 +0200 @@ -554,6 +554,8 @@ @DOCSTRING(license) +@DOCSTRING(memory) + @DOCSTRING(getrusage) @DOCSTRING(winqueryreg)
--- a/scripts/help/__unimplemented__.m Wed Apr 22 16:04:48 2020 +0200 +++ b/scripts/help/__unimplemented__.m Sat May 02 20:18:10 2020 +0200 @@ -981,7 +981,6 @@ "memmapfile", "memoize", "MemoizedFunction", - "memory", "mergecats", "meta.abstractDetails", "meta.class.fromName",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/miscellaneous/memory.m Sat May 02 20:18:10 2020 +0200 @@ -0,0 +1,210 @@ +######################################################################## +## +## Copyright (C) 2020 The Octave Project Developers +## +## See the file COPYRIGHT.md in the top-level directory of this +## distribution or <https://octave.org/copyright/>. +## +## This file is part of Octave. +## +## Octave is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <https://www.gnu.org/licenses/>. +## +######################################################################## + +## -*- texinfo -*- +## @deftypefn {} {} memory () +## @deftypefnx {} {[@var{userdata}, @var{systemdata}] =} memory () +## Display or return information about memory usage by Octave. +## +## @example +## @group +## memory () +## @result{} System RAM: 3934008 KiB, swap: 4087804 KiB +## Octave RAM: 170596 KiB, virt: 1347944 KiB +## Free RAM: 1954940 KiB, swap: 4087804 KiB +## Available RAM: 2451948 KiB, total: 6042744 KiB +## @end group +## +## @group +## [userdata, systemdata] = memory () +## @result{} userdata = +## scalar structure containing the fields: +## MaxPossibleArrayBytes = 6.1622e+09 +## MemAvailableAllArrays = 6.1622e+09 +## ram_available_all_arrays = 2.4883e+09 +## MemUsedMATLAB = 1.3825e+09 +## mem_used_octave = 1.3825e+09 +## ram_used_octave = 1.7824e+08 +## +## systemdata = +## scalar structure containing the fields: +## PhysicalMemory = +## scalar structure containing the fields: +## Available = 2.4954e+09 +## Total = 4.0284e+09 +## SystemMemory = +## scalar structure containing the fields: +## Available = 6.6813e+09 +## Total = 8.2143e+09 +## VirtualAddressSpace = +## scalar structure containing the fields: +## Available = 2.8147e+14 +## Total = 2.8147e+14 +## @end group +## @end example +## +## This function is implemented for Linux and Windows only. +## +## @seealso{computer, getpid, getrusage, nproc, uname} +## @end deftypefn + +function [userdata, systemdata] = memory () + + if (! isunix () && ! ispc ()) + if (nargout > 0) + error ('memory: function not yet implemented for this architecture'); + else + warning ('memory: function not yet implemented for this architecture'); + endif + return; + endif + + kiB = 1024; + [architecture, bits] = computer (); + + if (isunix ()) + ## Read values from pseudofiles + [status, meminfo] = lmemory (); + + ## FIXME: Query the actual size of the user address space, + ## e.g. with getrlimit (RLIMIT_AS, rlp) + if (log2 (bits) > 32) + ## 64bit platform + address_space = 2^48; # 256 TiB + else + ## 32bit platform + address_space = 3 * 2^30; # 3 GiB + endif + + total_ram = meminfo.MemTotal * kiB; + total_swap = meminfo.SwapTotal * kiB; + free_ram = meminfo.MemFree * kiB; + if isfield (meminfo, "MemAvailable") + available_ram = meminfo.MemAvailable * kiB; + else + ## On kernels from before 2014 MemAvailable is not present. + ## This is a rough estimate that can be used instead. + available_ram = (meminfo.MemFree + meminfo.Cached) * kiB; + endif + free_swap = meminfo.SwapFree * kiB; + used_ram = status.VmRSS * kiB; + used_virtual = status.VmSize * kiB; + avail_virtual = address_space - used_virtual; + + elseif (ispc ()) + [proc, sys] = __wmemory__ (); + + total_ram = sys.TotalPhys; + total_swap = sys.TotalPageFile; + available_ram = sys.AvailPhys; + free_swap = sys.AvailPageFile; + used_ram = proc.WorkingSetSize; + used_virtual = proc.PagefileUsage; + avail_virtual = sys.AvailVirtual; + address_space = sys.TotalVirtual; + + endif + + available = min (available_ram + free_swap, avail_virtual); + ram_available = min (available_ram, avail_virtual); + + ## FIXME: On 32bit systems, the largest possible array is limited by the + ## largest contiguous block in memory. + user.MaxPossibleArrayBytes = available; + user.MemAvailableAllArrays = available; + user.ram_available_all_arrays = ram_available; + user.MemUsedMATLAB = used_virtual; # For Compatibility + user.mem_used_octave = used_virtual; + user.ram_used_octave = used_ram; + + syst.PhysicalMemory.Available = available_ram; + syst.PhysicalMemory.Total = total_ram; + syst.SystemMemory.Available = available_ram + free_swap; + syst.SystemMemory.Total = total_ram + total_swap; + syst.VirtualAddressSpace.Available = avail_virtual; + syst.VirtualAddressSpace.Total = address_space; + + + if (nargout) + userdata = user; + systemdata = syst; + else + unitsize = kiB; + unitname = 'kiB'; + disp (sprintf ('Octave is running on %s', architecture)) + disp (sprintf ('System RAM: %9.0f %s, swap: %9.0f %s', + round (syst.PhysicalMemory.Total / unitsize), unitname, + round (total_swap / unitsize), unitname )) + disp (sprintf ('Octave RAM: %9.0f %s, virt: %9.0f %s', + round (user.ram_used_octave / unitsize), unitname, + round (user.mem_used_octave / unitsize), unitname)) + if (isunix ()) + ## The concept of free vs. available RAM doesn't seem to exist on Windows + disp (sprintf ('Free RAM: %9.0f %s, swap: %9.0f %s', + round (free_ram / unitsize), unitname, + round (free_swap / unitsize), unitname)) + endif + disp (sprintf ('Available RAM: %9.0f %s, total: %9.0f %s', + round (user.ram_available_all_arrays / unitsize), unitname, + round (user.MemAvailableAllArrays / unitsize), unitname)) + endif + +endfunction + +function [status, meminfo] = lmemory () + ## Read pseudo files to gather memory information on Linux + + ## Read the proc/self/status pseudofile + ## see https://linuxwiki.de/proc/pid#A.2Fproc.2Fpid.2Fstatus + ## It contains a variable number of lines with name-value pairs. + + f = fopen ('/proc/self/status'); + buffer = textscan (f, '%s %s', 'delimiter', ':\n'); + fclose (f); + for i = 1:size (buffer{1}, 1) + status.(buffer{1}{i}) = textscan (buffer{2}{i}){1}; + endfor + + ## Read the /proc/meminfo pseudofile + ## see https://linuxwiki.de/proc/meminfo + ## It contains a variable number of lines with name-value pairs. + + f = fopen ('/proc/meminfo'); + buffer = textscan (f, '%s %s', 'delimiter', ':\n'); + fclose (f); + for i = 1:size (buffer{1}, 1) + meminfo.(buffer{1}{i}) = textscan (buffer{2}{i}){1}; + endfor + +endfunction + + +%!testif ; isunix () || ispc () +%! [user, syst] = memory (); +%! assert (user.mem_used_octave > 0); +%! assert (user.ram_used_octave <= user.mem_used_octave); +%! assert (user.mem_used_octave < syst.SystemMemory.Total); +%! assert (user.MemAvailableAllArrays <= syst.SystemMemory.Available); +