Memory+usage+monitor

//by Richard Russell, May 2007//


 * //This facility is now more conveniently available as an Add-In Utility//**

It is sometimes useful to be able to monitor memory usage (for example heap and stack size) while a program is running. This can alert you to problems like a //memory leak// (increasing and irreversible use of memory, eventually resulting in a 'No room' error) or wasteful use of memory resources (e.g. excessive string //garbage//).

Whilst you can always add your own code to monitor and report memory usage, it can be inconvenient and awkward to do so without disrupting your program's normal operation. This article lists a short routine which you can include in any program, which reports memory usage in a separate window:



The routine can most easily be activated by means of an [|ON TIME] interrupt, allowing it to run whatever your program is doing (within reason) and with the minimum need for modification to your program. Simply add the following statement near the beginning of your program:

code format="bb4w" ON TIME PROCmonitor : RETURN code This assumes you don't already have an **ON TIME** interrupt; if you do, add **PROCmonitor** to the code executed in the interrupt routine.

The values reported by **PROCmonitor** are as follows:


 * Total heap usage: the amount of memory being used to store your program's global variables, arrays, structures, string free space and memory allocated using [|DIM].
 * Total stack usage: the amount of memory being used to store your program's [|LOCAL] variables, arrays, structures, memory allocated using [|DIM LOCAL] and looping/nesting structures.
 * Total library usage: the amount of memory above HIMEM being used for [|INSTALLed] libraries.
 * String free space: the amount of memory freed by deallocating or re-sizing strings, and available for string storage.
 * Free heap/stack: the amount of memory available for growth of the heap and stack (without needing to increase the value of [|HIMEM]).

In each case the memory size is given in bytes. Note that in normal circumstances **heap** usage will never decrease (there are exceptions such as use of the [|CLEAR] statement, or deallocating a string at the top of the heap) but **stack** usage will increase and decrease, often by a considerable amount.

The **PROCmonitor** routine is listed below. Note that it automatically loads the **WINLIB2** library if required, but doesn't do so if it is already installed:

code format="bb4w" DEF PROCmonitor PRIVATE D%, L%     IF L% THEN ENDPROC L% = TRUE IF D%=0 THEN ON ERROR LOCAL RESTORE ERROR : INSTALL @lib$+"WINLIB2" D%=FN_newdialog("Memory usage monitor",50,50,149,102,8,570) D%!20 += 8 PROC_static(D%,"Total heap usage:",100,12,10,64,16,0) PROC_editbox(D%,"",101,79,9,56,12,&800) PROC_static(D%,"Total stack usage:",102,12,28,64,16,0) PROC_editbox(D%,"",103,79,27,56,12,&800) PROC_static(D%,"Total library usage:",104,12,46,64,16,0) PROC_editbox(D%,"",105,79,45,56,12,&800) PROC_static(D%,"String free space:",106,12,64,64,16,0) PROC_editbox(D%,"",107,79,63,56,12,&800) PROC_static(D%,"Free heap/stack:",108,12,82,64,16,0) PROC_editbox(D%,"",109,79,81,56,12,&800) PROC_showdialog(D%) ENDIF LOCAL B%, I%, P%, S%     DIM S% LOCAL -1 SYS "SetDlgItemInt", !D%, 101, END-LOMEM SYS "SetDlgItemInt", !D%, 103, HIMEM-S% SYS "SetDlgItemInt", !D%, 109, S%-END-512 P% = !360 IF P% THEN WHILE ?P% : P% += ?P% : ENDWHILE : P% = P%+4-!360 SYS "SetDlgItemInt", !D%, 105, P%     B% = 0 FOR I% = 0 TO 16 P% = @vdu%+512+4*I% WHILE !P% P% = !P% B% += (1<<I%)-1 ENDWHILE NEXT SYS "SetDlgItemInt", !D%, 107, B%     L% = FALSE ENDPROC code