Petr Schreiber
19-07-2006, 22:19
Hi,
please find very simple utility below. It serves to display current memory occupation.
I probably won't won a prize for coding skills 2006/2007 :) but it can be useful to see how much your ( or anybody else ) program "eats" the memory. Especially web browsers show interesting info sometimes ...
I recommend to put a shortcut on the desktop to be able to check it anytime.
' Basic info about memory occupation
' Useful to see leaks other ar your programs do :)
TYPE MEMORYSTATUS
dwLength AS DWORD
dwMemoryLoad AS DWORD
dwTotalPhys AS DWORD
dwAvailPhys AS DWORD
dwTotalPageFile AS DWORD
dwAvailPageFile AS DWORD
dwTotalVirtual AS DWORD
dwAvailVirtual AS DWORD
END TYPE
DECLARE function GlobalMemoryStatus LIB "KERNEL32.DLL" ALIAS "GlobalMemoryStatus" (lpBuffer AS MEMORYSTATUS) as long
dim lpBuffer AS MEMORYSTATUS
GlobalMemoryStatus (lpBuffer)
msgBox 0, "Physical memory:"+ $CRLF + _
"Available"+$TAB+FORMAT$(lpBuffer.dwAvailPhys/1024/1024, "0")+" MB"+ $CRLF + _
"Installed"+$TAB+FORMAT$(lpBuffer.dwTotalPhys/1024/1024, "0")+" MB"+ $CRLF + _
$CRLF + _
"Virtual memory:"+ $CRLF + _
"Available"+$TAB+FORMAT$(lpBuffer.dwAvailVirtual/1024/1024, "0")+" MB"+ $CRLF + _
"Installed"+$TAB+FORMAT$(lpBuffer.dwTotalVirtual/1024/1024, "0")+" MB"+ $CRLF + _
$CRLF + _
"General:"+ $CRLF + _
"Load"+$TAB+FORMAT$(lpBuffer.dwMemoryLoad, "0")+" %"+ $CRLF _
, %MB_OK or %MB_ICONINFORMATION, "Memory information"
Bye,
Petr
RobertoBianchi
20-07-2006, 08:32
Hi Petr,
very usefull, in my box with MS Outlook an IExplore opened I have a memory payload of 51%!
Thanks,
Roberto
Petr Schreiber
22-07-2006, 21:52
Hi,
thanks for reactions. Now comes more interesting sample - featuring progressbars and timer.
It is very interesting to see, how the free memory is getting loaded for example at startup of the Windows. On my box I start at 166 of 319 and end at 134 of 319 MB. Terrible :)
Hope you'll find it more interesting as it is refreshed every second.
The code is compilation of few "SampleScripts".
' Basic info about memory occupation
' Version 2.0 - visual presentation, updated every second !
uses "UI"
DIM hDlg AS DWORD
dim Msg, wparam,lparam as dword
TYPE MEMORYSTATUS
dwLength AS DWORD
dwMemoryLoad AS DWORD
dwTotalPhys AS DWORD
dwAvailPhys AS DWORD
dwTotalPageFile AS DWORD
dwAvailPageFile AS DWORD
dwTotalVirtual AS DWORD
dwAvailVirtual AS DWORD
END TYPE
DECLARE function GlobalMemoryStatus LIB "KERNEL32.DLL" ALIAS "GlobalMemoryStatus" (lpBuffer AS MEMORYSTATUS) as long
DECLARE FUNCTION KillTimer LIB "USER32.DLL" ALIAS "KillTimer" (BYVAL hWnd AS DWORD, BYVAL nIDEvent AS LONG) AS LONG
DECLARE FUNCTION SetTimer LIB "USER32.DLL" ALIAS "SetTimer" (BYVAL hWnd AS DWORD, BYVAL nIDEvent AS LONG, BYVAL uElapse AS DWORD, BYVAL lpTimerFunc AS LONG) AS LONG
global lpBuffer AS MEMORYSTATUS
%ID_TIMER = 5000
%PROG_BAR_1 = 1001
%PROG_BAR_2 = 1002
%PROG_BAR_3 = 1003
global hProgress1 as dword
global hProgress2 as dword
global hProgress3 as dword
DIALOG NEW 0, "Memory guardian", 0, 0, 210, 100, _
%WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU, _
%WS_EX_TOPMOST TO hDlg
CONTROL ADD LABEL, hDlg, 1000,"Physical memory", 5, 5, 200, 14
CONTROL ADD "msctls_progress32", hDlg, %PROG_BAR_1, "", 5, 20, 200, 10, %WS_CHILD OR %WS_VISIBLE OR %PBS_SMOOTH
CONTROL HANDLE hDlg, %PROG_BAR_1 TO hProgress1
CONTROL ADD LABEL, hDlg, 2000,"Virtual memory", 5, 35, 200, 14
CONTROL ADD "msctls_progress32", hDlg, %PROG_BAR_2, "", 5, 50, 200, 10, %WS_CHILD OR %WS_VISIBLE OR %PBS_SMOOTH
CONTROL HANDLE hDlg, %PROG_BAR_2 TO hProgress2
CONTROL ADD LABEL, hDlg, 3000,"Total load", 5, 65, 200, 14
CONTROL ADD "msctls_progress32", hDlg, %PROG_BAR_3, "", 5, 80, 200, 10, %WS_CHILD OR %WS_VISIBLE OR %PBS_SMOOTH
CONTROL HANDLE hDlg, %PROG_BAR_3 TO hProgress3
GlobalMemoryStatus (lpBuffer)
SetTimer hDlg, %ID_TIMER, 1000, %NULL
ProgressBar_SetRange32 (hProgress1, 0, lpBuffer.dwTotalPhys)
ProgressBar_SetPos (hProgress1, 50)
ProgressBar_SetBarColor (hProgress1, rgb(0,128,0))
ProgressBar_SetBkColor (hProgress1, rgb(128,0,0))
ProgressBar_SetRange32 (hProgress2, 0, lpBuffer.dwTotalVirtual)
ProgressBar_SetPos (hProgress2, 25)
ProgressBar_SetBarColor (hProgress2, rgb(0,128,0))
ProgressBar_SetBkColor (hProgress2, rgb(128,0,0))
ProgressBar_SetRange32 (hProgress3, 0, 100)
ProgressBar_SetPos (hProgress3, 25)
ProgressBar_SetBarColor (hProgress3, rgb(0,128,0))
ProgressBar_SetBkColor (hProgress3, rgb(128,0,0))
DIALOG SHOW modeless hDlg
while isWindow(hDlg)
Msg = GetMessage(hDlg, wParam, lParam)
select case Msg
case %WM_INITDIALOG
CASE %WM_TIMER
GlobalMemoryStatus (lpBuffer)
ProgressBar_SetPos (hProgress1, lpBuffer.dwAvailPhys)
ProgressBar_SetPos (hProgress2, lpBuffer.dwAvailVirtual)
ProgressBar_SetPos (hProgress3, 100-lpBuffer.dwMemoryLoad)
control set text hDlg, 1000, "Free physical memory ( "+format$(lpBuffer.dwAvailPhys/1024/1024, "0")+" of "+format$(lpBuffer.dwTotalPhys/1024/1024, "0")+" MB )"
control set text hDlg, 2000, "Free virtual memory ( "+format$(lpBuffer.dwAvailVirtual/1024/1024, "0")+" of "+format$(lpBuffer.dwTotalVirtual/1024/1024, "0")+" MB )"
control set text hDlg, 3000, "Total free load ( "+format$(100-lpBuffer.dwMemoryLoad, "0")+" % )"
CASE %WM_SYSCOMMAND
SELECT CASE wParam
CASE %SC_CLOSE
EXIT WHILE
END SELECT
END SELECT
wend
KillTimer hDlg, %ID_TIMER
DIALOG END hDlg
FUNCTION ProgressBar_SetRange32 (BYVAL hProgress AS DWORD, BYVAL iLowLim AS LONG, BYVAL iHighLim AS LONG) AS DWORD
FUNCTION = SendMessage (hProgress, %PBM_SETRANGE32, iLowLim, iHighLim)
END FUNCTION
FUNCTION ProgressBar_SetPos (BYVAL hProgress AS DWORD, BYVAL nNewPos AS LONG) AS LONG
FUNCTION = SendMessage (hProgress, %PBM_SETPOS, nNewPos, 0)
END FUNCTION
FUNCTION ProgressBar_SetBarColor (BYVAL hProgress AS DWORD, BYVAL clrBar AS LONG) AS LONG
FUNCTION = SendMessage (hProgress, %PBM_SETBARCOLOR, 0, clrBar)
END FUNCTION
FUNCTION ProgressBar_SetBkColor (BYVAL hProgress AS DWORD, BYVAL clrBk AS LONG) AS LONG
FUNCTION = SendMessage (hProgress, %PBM_SETBKCOLOR, 0, clrBk)
END FUNCTION
Bye,
Petr
ErosOlmi
31-07-2006, 12:17
Petr,
I just discover how good is this example !!!!!
Also, CPU load during script execution is close to zero.
Thanks a lot.
Request: can I add to official distribution?
Petr Schreiber
31-07-2006, 13:52
Hi Eros,
I'm glad you like it :)
The minimal CPU load is possible due to the timer.
If you like, please add it to the distribution
Thanks,
Petr
replwithoutacause
07-11-2020, 08:58
Hey everyone,
First time user of ThinBasic here and really enjoying it. I can really tell what a passion project this is for the developers!
So, onto my first question. I loaded the Memory.tbasic sample code and it is reporting incorrect information (showing 4GB of RAM when 16GB is actually installed), which is called out in Microsoft's own documentation (https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalmemorystatus) and so they recommend using the GlobalMemoryStatusEx (https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex) function instead. Where I am stuck is that the type this function expects has different parameters and with different types, particularly DWORDLONG. What is the equivalent of this in ThinBasic? The updated structure must look like this:
typedef struct _MEMORYSTATUSEX {
DWORD dwLength;
DWORD dwMemoryLoad;
DWORDLONG ullTotalPhys;
DWORDLONG ullAvailPhys;
DWORDLONG ullTotalPageFile;
DWORDLONG ullAvailPageFile;
DWORDLONG ullTotalVirtual;
DWORDLONG ullAvailVirtual;
DWORDLONG ullAvailExtendedVirtual;
} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;
Source: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-memorystatusex
Thanks!
:cool:
ErosOlmi
08-11-2020, 21:59
Ciao,
equivalent of DWORDLONG is QUAD in thinBasic. I will add DWORDLONG alias in next thinBasic release.
Here an example of GlobalMemoryStatusEx usage.
uses "console"
TYPE MEMORYSTATUSEX
dwLength AS DWORD
dwMemoryLoad AS DWORD
ullTotalPhys AS QUAD
ullAvailPhys AS QUAD
ullTotalPageFile AS QUAD
ullAvailPageFile AS QUAD
ullTotalVirtual AS QUAD
ullAvailVirtual AS QUAD
ullAvailExtendedVirtual AS QUAD
END TYPE
DECLARE function GlobalMemoryStatusEx LIB "KERNEL32.DLL" ALIAS "GlobalMemoryStatusEx" (lpBuffer AS MEMORYSTATUSEX) as long
global memStatusEx AS MEMORYSTATUSEX
memStatusEx.dwLength = SIZEOF(MEMORYSTATUSEX)
IF ISFALSE(GlobalMemoryStatusEx( memStatusEx )) THEN
print "Error"
else
printl "Memory:"
printl "Total bytes", memStatusEx.ullTotalPhys
printl "Available bytes", memStatusEx.ullAvailPhys
end If
printl "Press a key to end"
WaitKey
ReneMiner
08-11-2020, 23:34
ull = unsigned long long, i would use the quad-type since it provides the 64 bits.
Alternative you can use 2 dwords and calculate Number X = dw1 + dw2 * 4294967295
Its a matter of interpretation. No need to create an udt for original BYREF <name as type> passed parameters you can allocate a buffer that provides the required size or more and change the declaration to ByVal pBuffer As DWORD
' the functions declaration. Use ALIAS in thinBasic always and name it as you like
' since its of the WinAPI i am used to prefix it "Win_" & "<whatItDoes>"
Declare Function Win_ReadMemoryStatus Lib "kernel32.dll" alias "GlobalMemoryStatusEx" (byval pBuffer As Dword) As Long
' that one to check installed RAM:
Declare Function Win_GetRam Lib "Kernel32.dll" Alias "GetPhysicallyInstalledSystemMemory" (byval pUInt64_Ram_kB as dword) as Boolean
' the original declaration does not say ByVal nor ByRef for the lpMemoryStatusEx
' but if none it means ByRef in the WinAPI while thinBasic defaults to ByVal if
' not given.
' You can use ByRef but then you must create a variable-type
' that matches the original type at least in size.
' How you read it is up to you
' instead of passing a matching type ByRef we can use a Dword that holds a pointer
' it must point to any buffer where the api-function will find the required space
' you can use a dynamic string, fixed length string or just any allocated memory,
' even a variable if its large enough (see Win_GetRam) using a quad (2*32 Bit) as
' buffer.
'
' DWORD dwLength;
' DWORD dwMemoryLoad;
' DWORDLONG ullTotalPhys;
' DWORDLONG ullAvailPhys;
' DWORDLONG ullTotalPageFile;
' DWORDLONG ullAvailPageFile;
' DWORDLONG ullTotalVirtual;
' DWORDLONG ullAvailVirtual;
' DWORDLONG ullAvailExtendedVirtual"
'
'' now it remains the names only delimited by semicolon ";"
' parse the names to an array of string
string SubElement$()
parse "dwLength;dwMemoryLoad;ullTotalPhys;ullAvailPhys;ullTotalPageFile;ullAvailPageFile;ullTotalVirtual;ullAvailVirtual;ullAvailExtendedVirtual",
SubElement$, ";"
' the MEMORYSTATUSEX structure contains 9 elements of 2 types
' 2 32Bit-dwords and
' 7 64Bit-dwords - altogether 64 bytes
' so create a buffer of 64 bytes
' pStatus contains where the buffer starts
Dword pStatus = heap_Alloc(64)
' dwLength is a subelement that must contain the buffer size
' as the information on microsoft says -look up- its the
' very first four bytes of our buffer at pStatus
' lets have virtually an array of Dword upon the buffer that
' covers the allocated 64 bytes completely
dim vDword(heap_Size(pStatus)/SizeOf(Dword)) As Dword at pStatus
' now Heap_Size(pStatus) is 64 bytes
' sizeof(Dword) is 4
' 64/4 = we have created an array of 16 DWord-elements At pStatus
' or
' we assigned the names vDword(1) to vDword(16) to that memory area
' which starts at the position contained in pStatus that we can access
' using HEAP_-functions as well
' dwLength was the first? and must contain the buffers size- ok:
vDword(1) = Heap_Size(pStatus)
' thats the same as
Poke(Dword, pStatus, 64)
' now call, provide the VALue in pStatus ByVal- the address of our buffer
Long lResult = Win_ReadMemoryStatus(pStatus)
' instead of passing a variable byref
String sResult = "Memory status resulted 0x" & hex$(lResult,8) & CRLF
sResult &= "Element " & repeat$(50,".") & " Value" & CRLF
' now we prepared the names in an array named Subelement$()
long l
Long Index = 1 ' arrays in thinBasic are 1-based
' this will keep track of virtual vDword
' but as the vartype is 64Bit unsigned LongLong
' (while LongLong were signed and equals Type Quad)
' lets try both: and have a quad-array upon the DWORDLONG
Dim vQuad(7) as Quad at pStatus + 8
' vQuad(1) will be after vDword(1) and vDword(2) each 4 bytes, so + 8
' l will be 3 already (3rd subelement) upon vQuad(1) means to subtract 2 of l
' if memory is interpreted as Quad. if there were negative numbers we could
' use Type NUMBER (10 bytes) and multiply the HI vDword of each pair with
' the highest value in range of dword and add the LO of the dword-pair
Dword dwRangeHigh = 0xFFFFFFFF
Number BigNumber
for l = 1 to 9
sResult &= subelement$(l) & " : "
if startsWith(subelement$(l), "dw") Then
' current Element is a Dword
sResult &= tstr$(vDword(Index)) & crlf
' 1 more vDword was used:
Index += 1
Else
' starts with "ull"
' first As QUAD
sResult &= tstr$(vQuad(l-2)) & Repeat$(2, $Tab)
' then As NUMBER
BigNumber = vDword(Index) + dwRangeHigh * vDword(Index+1)
sResult &= tstr$(BigNumber) & CRLF
Index += 2 ' used 2 of vDword to display this
EndIf
Next
' append 1 more line since the last one ends with a newline
quad ram_in_kB
Boolean bRes = Win_GetRam(varptr(ram_in_kB))
sResult &= "Ram in MB = " & str$(ram_in_kb\1024)
'##################################
'### finally present the result ###
'##################################
msgBox sResult, %MB_ICONINFORMATION | %MB_OK, "Memory information"
replwithoutacause
09-11-2020, 07:13
Eros and Rene, that is exactly the information I was looking for. Thank you very much for the help!
replwithoutacause
09-11-2020, 07:29
Eros, the idea of adding the DWORDLONG alias is a good one and will help newcomers like me. Thank you for showing me an implementation which utilizes the GlobalMemoryStatusEx function!
Rene, I read every line of your explanation and I must say, you elucidated many new concepts for me by taking the time to break it down. I am thoroughly impressed with your explanation, but not surprised after reading through the entire thinIce thread.
Thanks again you guys. Take care. :cool:
ErosOlmi
09-11-2020, 13:53
Even if thinBasic is an interpreted languages we have added many native supported data types: https://www.thinbasic.com/public/products/thinBasic/help/html/index.html?numericvariables.htm
We have also added some alias in order to simplify code porting from other languages.