1. ExamineStorage.bcd
ExamineStorage.bcd is a module that assists in examining the state of the SafeStorage heap. Most users will only be interested in the TakeHeapStats command.
FindCyclicTypes Command
FindCyclicTypes is similar to TakeHeapStats, but will only report on objects that are involved in cycles (i.e., that can reach themselves by following REFs). The output and switches are similar to TakeHeapStats.
The best way to use this command is to execute "TakeHeapStats" once to get base statistics, then to run the program you suspect of creating cyclic objects, then to execute "TakeHeapStats -d" to see the differences.
The following switches control the behavior of FindCyclicTypes (defaults in parens):
-d: (FALSE) print delta statistics
-g: (TRUE) GC once before taking stats
-n: (FALSE) no save of stats for next time
-o: (FALSE) show objects rank
-r: (FALSE) reprint only, don't take stats
-s: (FALSE) silent, don't print stats
-w: (TRUE) show words rank
Printing is governed by the same variables as TakeHeapStats. As a side benefit, the heap is validated when performing the scan.
FindBadGuys Command
FindBadGuys is a command to find suspect objects and print information about them. The "bad" predicate is based on the value of variables in the global frame ExamineStorage. These variables are:
minType: minimum type code to be found (default SafeStorage.nullType)
maxType: maximum type code to be found (default [LAST[SafeStorage.TypeIndex]])
allowF: TRUE => can find finalizable objects (default TRUE)
allowNotF: TRUE => can find non-finalizable objects (default TRUE)
allowOver: TRUE => can find objects with overflowed counts (default TRUE)
allowNotOver: TRUE => can find objects with non-overflowed counts (default TRUE)
minBsi: minimum block size for found objects (default FIRST[Allocator.BlockSizeIndex])
maxBsi: maximum block size for found objects (default LAST[Allocator.BlockSizeIndex])
minRC: minimum block size for found objects (default FIRST[Allocator.RefCount])
maxRC: maximum block size for found objects (default LAST[Allocator.RefCount])
An object must pass all of the tests in order to be found. However, as a minor implementation limitation, only the first 64 bad guys will be displayed. As an example, to find all objects with overflowed reference counts, do the following:
Run ExamineStorage
← ExamineStorage.allowNotOver ← FALSE
FindBadGuys
Note that the variables ExamineStorage.typeDepth and ExamineStorage.typeWidth specify the depth and width for the printing of types.
As a side benefit, the heap is validated when performing the scan.
ExamineRefs Procedure
OK, so you've done TakeHeapStats, and you found out that most of your storage is going into ropes; the next question is, who owns those ropes? ExamineRefs is for getting the answer.
ExamineRefs: PROC [goalList, transparentList: TypeList, log: STREAM, gcFirst, wordRank: BOOL ← TRUE, objectRank: BOOL ← FALSE]
It will scan memory, looking for references to objects whose type is equivalent to one in the goalList. It keeps track of how many times such a reference is made from each type of object, and how many words worth of referent each such reference makes from each type of object. Now, the next thing you'd notice is that a lot of your interesting stuff is owned by the cons cells of LIST OF REF ANYs, which is also boring --- you want to credit the reference to whoever owns the LIST OF REF ANY. This is what the transparentList argument is for. The references credited to an object are not only those contained directly in that object, but also those reachable by tracing through REFs to objects whose types are equivalent to ones in the transparentList. A couple of convenient values for transparentList are provided in basicBores and moreBores.
% ← ExamineStorage.ExamineRefs[goalList: LIST[CODE[Rope.RopeRep]], transparentList: ExamineStorage.moreBores, log: &stdout[]]
-- Heap storage statistics (June 9, 1986 10:36:41 pm PDT) --
types: 98, objects: 51198, words: 858522 (words/obj: 17)
RC - 0: 0, 1: 0, 2: 0, 3: 0
RC - 4: 0, 5: 0, 6: 0, 7: 0
RC - 8: 0, 9: 0, 10: 0, 11: 0
RC - 12: 0, 13: 0, 14: 0, 15: 0
RC IN [16..31]: 0, IN [32..63]: 0, overflow: 0
inZCT: 0, inZCT0; 0
-- Rank by words --
rank 0, words: 260438, objects: 15765, type: 1421B
TextNode.Body
rank 1, words: 236900, objects: 14302, type: 752B
RECORD[in: STREAM ← NIL, out: STREAM ← NIL, err: STREAM ← NIL, commandLine: ROPE, ...]
rank 2, words: 123702, objects: 7178, type: 1424B
EditNotify.Change
rank 3, words: 109480, objects: 6041, type: 24B
SafeStorageOpsImpl.RefLitTable
rank 4, words: 28038, objects: 1603, type: 1360B
RopeReader.Body
rank 5, words: 22470, objects: 2215, type: 35B
AtomPrivate.AtomRec
rank 6, words: 15696, objects: 283, type: 535B
Commander.CommandProcObject
rank 7, words: 14392, objects: 730, type: 2770B
WalnutMsgSetDisplayerPrivate.MsgInfoRec
rank 8, words: 6036, objects: 354, type: 1461B
NodePropsImpl.NodePropsBody
rank 9, words: 4184, objects: 357, type: 1252B
ViewerClasses.ViewerRec