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]&