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

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[];
LoadJavaClass["java.lang.management.ManagementFactory"];
JavaBlock[
  {#, java`lang`management`ManagementFactory`getOperatingSystemMXBean[]@#[]} & /@
  { getName
  , getArch
  , getVersion
  , getCommittedVirtualMemorySize
  , getFreePhysicalMemorySize
  , getFreeSwapSpaceSize
  , getTotalPhysicalMemorySize
  , getTotalSwapSpaceSize
  , getProcessCpuTime
  , getAvailableProcessors
  , getSystemLoadAverage
  } // 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
          getSystemLoadAverage           -1.

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


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}

On Windows with an external call:

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

Tags:

Memory