Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I find the size of RAM programmatically?

Status
Not open for further replies.

IRABYY

Programmer
Apr 18, 2002
221
US
Fellows,

I need to find the total size of physical RAM on the box programmatically (for speed optimization).

"Wintage" ( [wink] ) functions like SYS(12) or SYS(1001) ain't no help at all.

Function SYS(3050) is not of much help either: it gives you approx 65% of total RAM for the foreground run, and approx. 16% for the background run. Those are default VFP (or WinOS?) settings (well, at least on my machine, anyway).

However, according to the article "Set Turbo On: How Visual FoxPro Memory Usage Affects Performance" by Flavio Almeida and Walter Loughney (FoxTalk, Feb. 1997 issue), the best performance was achieved when the (foreground) buffer memory size is set to approx. 45%-50% of total physical RAM.

But I have to first find out that physical RAM size, don't I? I could have just

Code:
lnTotalRAM = VAL(SYS(3050, 1))/.65

but that would be kinda "malpractice", wouldn't it?

There's also WinAPI function:

BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)

The problem is that LPMEMORYSTATUSEX is a structure, that is defined in C as

typedef struct _MEMORYSTATUSEX {
DWORD dwLength;
DWORD dwMemoryLoad;
DWORDLONG ullTotalPhys;
DWORDLONG ullAvailPhys;
DWORDLONG ullTotalPageFile;
DWORDLONG ullAvailPageFile;
DWORDLONG ullTotalVirtual;
DWORDLONG ullAvailVirtual;
DWORDLONG ullAvailExtendedVirtual;
} MEMORYSTATUSEX

As far as I know, there's no structure data type in Fox.
Besides, when I tried to DECLARE and test this function off the Command window in VFP (7.0 SP1, to be exact), like

DECLARE INTEGER GlobalMemoryStatusEx IN Kernel32.dll @lpBuffer
DECLARE scrArr(9)
scrArr[1]=32*9
scrArr[2]=0
scrArr[3]=0
scrArr[4]=0
scrArr[5]=0
scrArr[6]=0
scrArr[7]=0
scrArr[8]=0
scrArr[9]=0
?GlobalMemoryStatusEx(@scrArr)

it gave me that notorious error message:
"Cannot find entry point GlobalMemoryStatusEx in the DLL" [sad]

Is there any way around?
Bottom line: how do I find the size of RAM on the box programmatically?

AHWBGA

Regards,

Ilya


 
Ilya,

Use GlobalMemoryStatus only, don't use the GlobalMemoryStatusEx. The extended only used for PC with more than 4 Gig RAM.

Here is the code you want.
Code:
Declare GlobalMemoryStatus in kernel32 String @lpBuffer
lpBuffer = replicate(chr(0), 4*8)
GlobalMemoryStatus(@lpBuffer)
?'Physical memory: ' + transform(Num2DWord(substr(lpBuffer,9,4)) / 1024, '@B 99,999,999 KBytes')

Function Num2DWord
   Return ;
      Asc(SUBSTR(lcBuffer, 1,1)) + ; 
      Asc(SUBSTR(lcBuffer, 2,1)) * 256 +; 
      Asc(SUBSTR(lcBuffer, 3,1)) * 65536 +; 
      Asc(SUBSTR(lcBuffer, 4,1)) * 16777216 
EndFunc
Hth
 
Oops.. I missed something in Num2DWord function

Function Num2DWord
LParameters lcBuffer

Regards
 
DECLARE GlobalMemoryStatus IN kernel32 STRING @lpBuffer

*|typedef struct _MEMORYSTATUS {
*| DWORD dwLength; 0:4
*| DWORD dwMemoryLoad; 4:4
*| SIZE_T dwTotalPhys; 8:4
*| SIZE_T dwAvailPhys; 12:4
*| SIZE_T dwTotalPageFile; 16:4
*| SIZE_T dwAvailPageFile; 20:4
*| SIZE_T dwTotalVirtual; 24:4
*| SIZE_T dwAvailVirtual; 28:4
*| } MEMORYSTATUS, *LPMEMORYSTATUS; total 32 bytes
#DEFINE MEMORYSTATUS_SIZE 32

PRIVATE cBuffer
cBuffer = REPLI(Chr(0), MEMORYSTATUS_SIZE)
= GlobalMemoryStatus (@cBuffer)

= _displ("Memory in use, % ...................", 5)
= _displ("Physical memory, in bytes ..........", 9)
= _displ("Physical memory available, bytes ...", 13)
= _displ("Committed memory limit, bytes ......", 17)
= _displ("Available memory to commit, bytes ..", 21)
= _displ("User mode portion..., bytes ........", 25)
= _displ("Unreserved/uncommitted memory ......", 29)

PROCEDURE _displ(lcCaption, nOffs)
LOCAL nSize
nSize = buf2dword(SUBSTR(cBuffer,nOffs,4))
? lcCaption + " " + ALLTRIM(TRANS(nSize, "999,999,999,999,999,999"))

FUNCTION buf2dword(lcBuffer)
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ;
BitLShift(Asc(SUBSTR(lcBuffer, 2,1)), 8) +;
BitLShift(Asc(SUBSTR(lcBuffer, 3,1)), 16) +;
BitLShift(Asc(SUBSTR(lcBuffer, 4,1)), 24)
Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
My the greatest thanks to you both, colelagues! This works!

I especially like this conversion char-to-DWORD!

All right, problem is solved, case is closed!

Thank you again!

Regards,

Ilya
 
You're welcome Ilya.
Glad to hear that works for you :)

Regards
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top