Sei sulla pagina 1di 2

Print Article

Seite 1 von 2

Issue Date: FoxTalk January 1998

Play Tricks on Your Memory


Gary DeWitt

Quick -- how much physical memory is on your user's computer? How much of that isn't in use? How much has been paged to virtual memory? Here's a look at how the Windows API can help you quickly answer these and other questions about memory.
One of my company's resellers once called our tech support line while in the middle of giving a demo to a prospective client. He'd installed our application on his laptop and rushed to see a prospect to show it off. Things weren't going so well. Performance was sluggish and some features just didn't work properly at all. Our tech support manager listened carefully to the symptoms and thought it sounded like insufficient memory. The salesman said he had 16M of RAM, which, as you well know, is the practical minimum for VFP 3.0 in Windows 95. On a hunch, our tech support manager asked the reseller to open the About dialog box on our Help menu. On page 2, it said that he had only 8M! Furthermore, he had 80M of virtual memory, almost all of which was used. As you can imagine, we lost the sale. But the reseller learned a valuable lesson in just a few seconds, and our tech support manager didn't have to spend minutes trying to walk him through the Control Panel to try to find out about his system. Using GlobalMemoryStatus() The GlobalMemoryStatus() function in the Win32 API can give you all the information I mentioned above and much more. In the October and November 1997 issues (see "Gain Control Using the Windows API" and "Is it Real, or is it . . ." respectively), I showed you how to imitate C structures with strings and pass pointers. You'll need that knowledge to call GlobalMemoryStatus (), which has a void return type (it returns nothing) and accepts a single argument, a pointer to a MEMORYSTATUS structure. Here's the C definition of the structure: typedef struct _MEMORYSTATUS { DWORD dwLength; // size of structure DWORD dwMemoryLoad; // % of memory in use DWORD dwTotalPhys; // physical memory DWORD dwAvailPhys; // free physical memory DWORD dwTotalPageFile; // bytes of swap file DWORD dwAvailPageFile; // swap file free DWORD dwTotalVirtual; // total address space DWORD dwAvailVirtual; // free address space } MEMORYSTATUS, *LPMEMORYSTATUS; This structure consists of eight DWORDs of four bytes each. To pass it to GlobalMemoryStatus(), you must create a 32-byte string of zeros, declare GlobalMemoryStatus(), and pass the string by reference, which passes a pointer to the string: lpMemoryStatus = REPLICATE(CHR(0), 32) DECLARE GlobalMemoryStatus IN Win32API ; STRING @lpMemoryStatus GlobalMemoryStatus(@lpMemoryStatus) To parse the string into the structure's individual members, use the CharToBin() function (included in the accompanying Download file ), which I introduced in my November 1997 column. Each value consists of four bytes. Parse the string into four-byte chunks and convert them to numbers with CharToBin(). My variable naming convention with API functions is to use the same names as in the C documentation, rather than my normal VFP variable names. This helps me to keep track of the meaning of the variables more easily. I skip the first four bytes, as they hold no useful data. dwMemoryLoad = ; CharToBin(SUBSTR(lpMemoryStatus, dwTotalPhys = ; CharToBin(SUBSTR(lpMemoryStatus, dwAvailPhys = ; CharToBin(SUBSTR(lpMemoryStatus, dwTotalPageFile = ; CharToBin(SUBSTR(lpMemoryStatus, dwAvailPageFile = ; CharToBin(SUBSTR(lpMemoryStatus, dwTotalVirtual = ; CharToBin(SUBSTR(lpMemoryStatus, dwAvailVirtual = ; CharToBin(SUBSTR(lpMemoryStatus,

5, 4)) 9, 4)) 13, 4)) 17, 4)) 21, 4)) 25, 4)) 29, 4))

http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 07.02.06

Print Article

Seite 2 von 2

I ran this code in my system as I was writing this article and it showed: Memory Load = 87 Total Physical RAM = 33,067,008 Available RAM = 376,832 Total Page File = 344,522,752 Available Page File = 326,672,384 Total Virtual = 2,143,289,344 Available Virtual = 2,115,829,760 Obviously, the preceding numbers show that my system is over-utilized. Only 368K of my 32M of physical memory is free, even though I theoretically have 356M free, including virtual memory. This could seriously affect the performance of my system. In FoxPro, this could have a particularly significant effect on the performance of features such as SQL queries and indexing, where FoxPro attempts to speed performance by keeping as much of the results in memory as possible. Putting GlobalMemoryStatus() to use Reporting memory usage in our application's About dialog box makes it easy for our tech support department to diagnose performance problems. If I reported the above numbers, I'd certainly hope someone would recommend I invest in more RAM! If your application is written in VFP 3.0, making memory upgrade recommendations is about all you can do. But with VFP 5.0, you can use this same information to automatically fine-tune performance. The SYS(3050) function allows you to set the amount of memory VFP allocates to data buffers (see the article "Set Turbo On: How Visual FoxPro Memory Usage Affects Performance" in the February 1997 issue of FoxTalk). Best performance is achieved when all the buffering is done in physical memory and none in virtual memory, as the virtual memory is actually on disk and defeats the whole purpose of buffering tables. In an over-utilized system, you can often improve the performance of queries by setting SYS(3050, 1) to a value equal to or slightly less than the actual amount of physical RAM available: lpMemoryStatus = REPLICATE(CHR(0), 32) DECLARE GlobalMemoryStatus IN Win32API ; STRING @lpMemoryStatus GlobalMemoryStatus(@lpMemoryStatus) dwAvailPhys = ; CharToBin(SUBSTR(lpMemoryStatus, 13, 4)) SYS(3050, 1, dwAvailPhys) You might want to run some tests to determine whether the best value for queries is equal to the dwAvailPhys or some percentage less than dwAvailPhys. Because memory usage is volatile, you'll find that GlobalMemoryStatus() gives different values every time it's called. You might find it useful to call GlobalMemoryStatus() prior to each large query or during a reindexing procedure in order to continually optimize performance.

http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 07.02.06

Potrebbero piacerti anche