$!-----------------------------------------------------------------------------+ $! MEM.COM - Show memory management information similar to MONITOR SYSTEM | $!-----------------------------------------------------------------------------+ $! Author: Harry Flowers VMS Version: V5.3-1 (version dependent) $! [Memory addresses may need to be changed for different versions of VMS] $! $! Anything passed in P1 will cause a change to a 132 column display. $! (This does not add to the information, just increases granularity.) $! Anything passed in P2 will cause MONITOR SYSTEM,PAGE for 45 seconds. $! $! This procedure basically presents a more detailed breakdown than the $! memory section of a MONITOR SYSTEM. Unlike MONITOR, the scale for $! the free and modified pages is the same. Like monitor, the vertical $! bar in the page fault display represents the break between hard faults $! and soft faults. The goal is to show what is happening with the last $! ten percent of free memory and how the SYSGEN parameters affect this. $! $ SAVERIFY = F$VERIFY(0) ! Turn off verification $ SET NOON ! Ignore errors $ ESC[0,8] = 27 ! ESCape character $ SAY = "WRITE SYS$OUTPUT" ! Lots of output $ ON CONTROL_Y THEN GOTO ABORTED ! ^C and ^Y trap $ OLDISPLAY = F$GETDVI("TT:","DEVBUFSIZ") ! Save TT_WIDTH $ IF P2 .NES. "" THEN MONITOR SYSTEM,PAGE/END="+00:00:45" ! Monitor $ IF P1 .NES. "" THEN SET TERM/WIDTH=132 ! Set 132 if requested $ DISPLAY = F$GETDVI("TT:","DEVBUFSIZ") - 7 ! Bar display size $ SCRLEN = F$GETDVI("TT:","TT_PAGE") ! Screen length $ INTERVAL = 1 ! Beginning interval $! $! Get the system configuration information $ LAST_FAULTS = F$CVUI(0,32,F$FAO("!AD",4,%X80004078)) ! PMS$GL_FAULTS $ LAST_HFAULTS = F$CVUI(0,32,F$FAO("!AD",4,%X8000407C)) ! PMS$GL_RDFLTS $ MMG$GL_MAXPFN = F$CVUI(0,32,F$FAO("!AD",4,%X80008478)) ! Pageable mem $! Freelist is a very rough approximation of the total possible size of $! the free page list. A more accurate figure is not required here. $ FREELIST = MMG$GL_MAXPFN + 1 - (F$GETSYI("PAGEDYN")/512) ! Roughly $ FREELIM = F$GETSYI("FREELIM") ! These are all SYSGEN $ FREEGOAL = F$GETSYI("FREEGOAL") ! parameters of the $ BORROWLIM = F$GETSYI("BORROWLIM") ! same name, gotten $ GROWLIM = F$GETSYI("GROWLIM") ! via F$GETSYI so that $ MPW_HILIMIT = F$GETSYI("MPW_HILIMIT") ! we don't have to use $ MPW_LOLIMIT = F$GETSYI("MPW_LOLIMIT") ! new memory addresses $ MPW_THRESH = F$GETSYI("MPW_THRESH") ! for later versions of $ MPW_WAITLIMIT = F$GETSYI("MPW_WAITLIMIT") ! VMS (we could have $ MPW_LOWAITLIMIT = F$GETSYI("MPW_LOWAITLIMIT") ! read memory directly) $ FREEMAX = FREEGOAL ! Find the largest freelist SYSGEN parameter $ IF BORROWLIM .GT. FREEMAX THEN FREEMAX = BORROWLIM $ IF GROWLIM .GT. FREEMAX THEN FREEMAX = GROWLIM $ FASTINT = (FREELIM*2 + FREEMAX)/3 ! Fast update interval mark $ TRMSCALE = FREELIST/(DISPLAY*10) ! Show 10% of freelist $! $! Display the template (relatively static) information $! (Some of these are "dynamic" SYSGEN parameters) $ SAY F$FAO("''ESC'[H''ESC'[J''ESC'#6!18* Free Memory !6AS!/",F$TRNLNM("SYS$NODE")) $ SAY F$FAO("''ESC'#6Modified List!/") $ SCALE = MPW_LOLIMIT/TRMSCALE - 1 $ IF SCALE .LT. 0 THEN SCALE = 0 $ SAY F$FAO("!6UL !''SCALE'* ^Lolimit",MPW_LOLIMIT) $ SCALE = MPW_THRESH/TRMSCALE - 1 $ IF SCALE .LT. 0 THEN SCALE = 0 $ SAY F$FAO("!6UL !''SCALE'* ^Thresh",MPW_THRESH) $ SCALE = MPW_HILIMIT/TRMSCALE - 1 $ SAY F$FAO("!6UL !''SCALE'* ^Hilimit",MPW_HILIMIT) $ SCALE = MPW_LOWAITLIMIT/TRMSCALE - 1 $ SAY F$FAO("!6UL !''SCALE'* ^Lowaitlimit",MPW_LOWAITLIMIT) $ SCALE = MPW_WAITLIMIT/TRMSCALE - 1 $ SAY F$FAO("!6UL !''SCALE'* ^Waitlimit!/",MPW_WAITLIMIT) $ SAY F$FAO("''ESC'#6Free List!/") $ SCALE = FREELIM/TRMSCALE - 1 $ SAY F$FAO("!6UL !''SCALE'* ^Freelim",FREELIM) $ SCALE = FREEGOAL/TRMSCALE - 1 $ SAY F$FAO("!6UL !''SCALE'* ^Freegoal",FREEGOAL) $ SCALE = BORROWLIM/TRMSCALE - 1 $ SAY F$FAO("!6UL !''SCALE'* ^Borrowlim",BORROWLIM) $ SCALE = GROWLIM/TRMSCALE - 1 $ SAY F$FAO("!6UL !''SCALE'* ^Growlim!/",GROWLIM) $ SAY F$FAO("''ESC'#6Page Fault Rate") $ SAY "''ESC'[20;''SCRLEN'r" $! $! Display the dynamic information and bar graphs $ LOOP: $ SCH$GL_FREECNT = F$CVUI(0,32,F$FAO("!AD",4,%X80004018)) ! Free pages $ SCH$GL_MFYCNT = F$CVUI(0,32,F$FAO("!AD",4,%X8000401C)) ! Modified pages $ PMS$GL_FAULTS = F$CVUI(0,32,F$FAO("!AD",4,%X80004078)) ! Page faults $ PMS$GL_RDFLTS = F$CVUI(0,32,F$FAO("!AD",4,%X8000407C)) ! Hard page flts $ PCNT = (SCH$GL_FREECNT*100)/FREELIST ! % Free memory $ PFRATE = (PMS$GL_FAULTS - LAST_FAULTS)/INTERVAL ! Page flt rate $ HPFRATE = (PMS$GL_RDFLTS - LAST_HFAULTS)/INTERVAL ! Hard flt rate $ IF HPFRATE .GT. PFRATE THEN HPFRATE = PFRATE ! It happens $ LAST_FAULTS = PMS$GL_FAULTS ! Save faults $ LAST_HFAULTS = PMS$GL_RDFLTS ! Save hard flts $ SAY F$FAO("''ESC'[H''ESC'#6!%T !3UB%!/!/",0,PCNT) $ SCALE = SCH$GL_MFYCNT/TRMSCALE $ IF SCALE .GE. DISPLAY THEN SCALE = DISPLAY - 1 $ SAY F$FAO("!6UL ''ESC'(0!''SCALE'*a''ESC'(B''ESC'[K!/!/!/!/!/!/!/",SCH$GL_MFYCNT) $ SCALE = SCH$GL_FREECNT/TRMSCALE $ IF SCALE .GE. DISPLAY THEN SCALE = DISPLAY - 1 $ SAY F$FAO("!6UL ''ESC'(0!''SCALE'*a''ESC'(B''ESC'[K!/!/!/!/!/!/",SCH$GL_FREECNT) $ SCALE2 = HPFRATE*DISPLAY/500 $ IF SCALE2 .GE. DISPLAY THEN SCALE2 = DISPLAY - 1 $ SCALE = (PFRATE-HPFRATE)*DISPLAY/500 - 1 $ IF SCALE .LT. 0 THEN SCALE = 0 $ IF (SCALE + SCALE2 + 1) .GE. DISPLAY THEN SCALE = DISPLAY - SCALE2 - 2 $ SAY F$FAO("!6UL ''ESC'(0!''SCALE2'*a''ESC'(B|''ESC'(0!''SCALE'*a''ESC'(B''ESC'[K",PFRATE) $ SAY F$FAO("Last interval (sec): !UL''ESC'[K",INTERVAL) $! $! Calculate the wait interval; wait less as memory becomes scarce $ IF SCH$GL_FREECNT .LE. FASTINT $ THEN INTERVAL = 1 $ ELSE IF SCH$GL_FREECNT .LE. FREEMAX $ THEN INTERVAL = 2 $ ELSE IF PCNT .LE. 10 $ THEN INTERVAL = 5 $ ELSE INTERVAL = 10 $ ENDIF $ ENDIF $ ENDIF $ SECS = 60*'F$CVTIME(,,"MINUTE")' + 'F$CVTIME(,,"SECOND")' $ READ/END=ABORTED/ERROR=CALCINT/TIME='INTERVAL'/PROMPT="" SYS$COMMAND DUMMY $ CALCINT: ! Calculate the actual interval waited $ INTERVAL = 60*'F$CVTIME(,,"MINUTE")' + 'F$CVTIME(,,"SECOND")' - SECS $ IF INTERVAL .LT. 0 THEN INTERVAL = INTERVAL + 3600 $ IF INTERVAL .EQ. 0 THEN INTERVAL = 1 $ GOTO LOOP $! We calculate the actual interval because broadcasts reset the wait $! timeout timer. Also, you may hit CR to speed up displays. $! $ ABORTED: ! Abort (normal) ending for command procedure $ IF P1 .NES. "" THEN SET TERM/WIDTH='OLDISPLAY' ! Restore term width $ SAY "''ESC'(B''ESC'[1;''SCRLEN'r''ESC'[J[Finished]" ! Cleanup screen $ SAVERIFY = F$VERIFY(SAVERIFY) ! Restore verification $ EXIT ! And we're finished