How to find out the (current) free memory on the system?

Is there any way in Mathematica to find out the currently free memory on the system Mathematica runs on (like the utility free shows on the command line)? I've found out functions to show the memory occupied by Mathematica itself, but of course there are also other programs running on the system, taking their share of memory, so that number is not sufficient to estimate the free memory.

The background is that currently if I do something which might fill up my memory (and I don't forget to do it), I call free by hand, subtract a safety margin, and then use MemoryConstrained in order to prevent the memory to get completely filled up (with quite unpleasant consequences). I'd like to automate that. While I certainly could call free from Mathematica and parse its output for the number, I'd like to avoid that if I can (who knows if the next system update makes subtle changes to free and then the parsing fails to give the correct number).

-
this seems os-specific. maybe tag it as such if it is –  acl Jan 18 '12 at 14:59
Well, MemoryInUse[] is the polar opposite of free, I'd say... –  Ｊ. Ｍ. Jan 18 '12 at 15:00
@acl: Well, the concept of free memory is certainly not OS specific. The free utility is, but I'm after a Mathematica function (if it exists) which most likely wouldn't be (I don't think there is any OS Mathematica runs on where you cannot get an estimate of available memory). Of course, if none exists, my workaround (parsing output of free) would be OS specific, but that's not what I asked for (although if someone wants to write it for me, I wouldn't complain :-)). So the OS-independent answer would be either "The function is called so-and-so and used like this" or "There isn't any." –  celtschk Jan 18 '12 at 15:08
@R.M: I'd not expect Mathematica to add memory of all processes (I strongly doubt free does that either). I think that every OS will have some functionality to estimate free memory (guarantees cannot be given anyway because right after returning, another process might allocate memory), and I'd expect Mathematica to use that functionality. –  celtschk Jan 18 '12 at 15:11
fair enough. I doubt there is an OS-independent way of doing it, though. –  acl Jan 18 '12 at 15:19

You might be able to use JLink along with some undocumented behaviour of the Java class java.lang.management.ManagementFactory to get the information you seek:

Needs["JLink"]
InstallJava[];
JavaBlock[
{#, javalangmanagementManagementFactorygetOperatingSystemMXBean[]@#[]} & /@
{ getName
, getArch
, getVersion
, getCommittedVirtualMemorySize
, getFreePhysicalMemorySize
, getFreeSwapSpaceSize
, getTotalPhysicalMemorySize
, getTotalSwapSpaceSize
, getProcessCpuTime
, getAvailableProcessors
} // Grid
]


This works on Windows 7 (Mathematica 8, 64-bit):

Out[368]= getName                        Windows Vista
getArch                        amd64
getVersion                     6.1
getCommittedVirtualMemorySize  102449152
getFreePhysicalMemorySize      5997510656
getFreeSwapSpaceSize           14498115584
getTotalPhysicalMemorySize     8587284480
getTotalSwapSpaceSize          17172676608
getProcessCpuTime              6068438900
getAvailableProcessors         4


I don't have Mac or Linux boxes to hand at the moment to test whether it works there as well.

-
it works fine on OS X (your system is not only not being loaded, but in fact actively doing negative work???) –  acl Jan 21 '12 at 20:18
@acl Thanks for checking OS X. As for the negative work, everybody complains about the heat death of the universe but few do anything about it ;) –  WReach Jan 21 '12 at 20:28
Do you know why this shows Windows Vista and amd64? –  Mr.Wizard Jan 22 '12 at 7:41
@Mr.Wizard Windows 7 is a really just a marketing label slapped on a Vista release. It would seem that the name change happened too late to change it in the deepest parts of the OS. "amd64" is the name given to the original 64-bit instructions added to the x86 architecture. The name has stuck, although the term "x86-64" is sometimes used as a vendor-neutral term. It so happens that this workstation has an Intel CPU, not an AMD one, but the historical term is used nonetheless. –  WReach Jan 22 '12 at 16:31
I've just checked on Linux, it works there as well. Moreover, the output is a Grid instead of simply a string, thus parsing isn't necessary either. I've changed the accepted answer to yours. –  celtschk Jan 22 '12 at 20:58

On Windows with an external call:

ReadList["!typeperf \"\\Memory\\Available Bytes\" -sc 1", Word,
RecordLists -> True, WordSeparators -> {","}] // ToExpression@Part[#,2,2]&

-
+1. Great! But it does not work for localized versions of Windows: words "Memory" and "Available Bytes" are localized and English version does not work. For getting localized names one can use the typeperf -qx command. –  Alexey Popkov Aug 19 '12 at 14:29

Under Windows you can use NETLink for this (it requires Microsoft .NET v.2 or later to be installed). Two methods were discussed in this MathGroups thread: "Calling kernel.dll from Mathematica. 1", "Calling kernel.dll from Mathematica. 2".

One way is to get this information via a managed API (that is, in .NET itself):

Needs["NETLink"]
query = NETNew["System.Management.ManagementObjectSearcher",
"SELECT * FROM Win32_OperatingSystem"];
resultCollection = query@Get[];
mo = First[NETObjectToExpression[resultCollection]];
getFreePhysMemNet[] := (mo@Get[]; mo["FreePhysicalMemory"])


The function getFreePhysMemNet[] returns the amount of free physical memory in Kb. This method is 30 times slower than direct calling of the GlobalMemoryStatusEx function of kernel32.dll which is availiable both on 32 bit and 64 bit Windows systems (checked under Windows 7 x64). Here is the code:

Needs["NETLink"];
getFreePhysMem::internalError =
"globalMemoryStatusEx[memorystatusex] has not returned True.";
If[$OperatingSystem === "Windows", memorystatusex = Symbol["LoadedNETTypes"][]; globalMemoryStatusEx = Symbol["DefineDLLFunction"][ "[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class MEMORYSTATUSEX {public uint dwLength; public uint dwMemoryLoad; public ulong ullTotalPhys; public ulong ullAvailPhys; public ulong ullTotalPageFile; public ulong ullAvailPageFile; public ulong ullTotalVirtual; public ulong ullAvailVirtual; public ulong ullAvailExtendedVirtual; public MEMORYSTATUSEX() {this.dwLength = (uint) Marshal.SizeOf(typeof( MEMORYSTATUSEX ));}} [return: MarshalAs(UnmanagedType.Bool)] [DllImport(\"kernel32.dll\", CharSet=CharSet.Auto, \ SetLastError=true)] public static extern bool GlobalMemoryStatusEx([In, Out] \ MEMORYSTATUSEX lpBuffer);"]; memorystatusex = Complement[Symbol["LoadedNETTypes"][], memorystatusex][[1, 1]]; memorystatusex = memorystatusex <> "+MEMORYSTATUSEX"; memorystatusex = Symbol["NETNew"][memorystatusex]; getFreePhysMem[] := If[TrueQ[globalMemoryStatusEx[memorystatusex]], memorystatusex@ullAvailPhys, Message[getFreePhysMem::internalError]; Abort[];$Failed]];


The function getFreePhysMem[] returns the amount of free physical memory in bytes.

Timings:

In[10]:= Do[getFreePhysMemNet[], {100}] // AbsoluteTiming
Do[getFreePhysMem[], {100}] // AbsoluteTiming
%%/%

Out[10]= {1.9218750, Null}

Out[11]= {0.0625000, Null}

Out[12]= {30.7500, 1}

-
The trouble, of course, is that not all OS's are equal in this regard. I don't know of a Mac OS X built-in command equivalent to the Linux free`, but you can locate Python scripts that will do the equivalent thing.