1 LISP LIBRARY PACKAGES MANUAL 1 LISP LIBRARY PACKAGES MANUAL SPY 1 PROGRAM ANALYSIS 1 SPY 6 Spy is a tool to help you make programs run faster. It gives you a picture of where the program is spending its time. Spy has two parts: a sampler'' that you run while running your program, which monitors what the program is doing, and a displayer'' that displays the data gathered by the sampler. The "sampler'' periodically interrupts the running program to account the functions in the current call stack. This allows Spy to remember not only (proportionally) how long is spent in each individual function, but also how long each function is seen on the call stack. The sampler data structures were designed to minimize interference with the normal running of the program%there is little noticable performance degradation. Because Spy doesn't log every call and return, you can run it even over long computations, unlike PCallStats. The "displayer'' uses the Grapher package to display the data gathered by the sampler. In the graph, the height of each node is adjusted to be proportional to the amount of time. Just as Masterscope and Browser give an interactive picture of the static structure of the program, Spy gives an interactive picture of the dynamic structure. The displayer is interactive as well as graphical. That is, you can look at the data in a variety of ways, since it seems there is no one picture that says it all. Since the displayer knows the whole call graph, it can show the entire tree structure (with separate calls to a function accounted separately) or merging separate calls to the same functions. Since the sampler records the entire calling stack when it samples, it can account for both individual and cumulative time. When the sampler runs, if a function is on the top of the stack, it adds to its individual total; if the function is on the stack at all, the sampler adds to the cumulative total. When there are several calls to the same function within the graph, the displayer can either merge'' the nodes (show the total time for the function in one node) or not. If a node is merged, then one of the boxes in the graph will have all of the time for that function accounted to it, and the rest will be left as ghost'' boxes. Spy has a variety of ways of controlling which nodes will be merged. 2 How to Use SPY 1 (SPY.BUTTON) [Function] This function puts up a little window, which you can use to turn Spy on and off. When Spy isn't watching, it looks like this: @C0Cll0lf` f`Ͼc f fl fl fl f#CȠnCȂ #TҗꀓU? #SQSߥ#@ Hs@Ђ%ksʤ(AD_sUʥ. _sľA&+o@VYW lwre# @SQiRLPCE J` ISĔ@DE+RC@#~C °DDG ?F"CP^$DCtz%7 CͷwF}CȂ,# Pushing it once will turn on sampling, and the window will look like this: @C0ll0lf` f`c l` l`l l`l l`l l``ȠnCȂ #TҗꀓU? SQSߥ#@ Hs@Ђ%ksʤ(AD_sUʥ. _sľA&+o@VYU lRe#/@SUOZR RCDԉR+SČ}]/C´_#¹/_C/AMtW &,CP_@CA BV C @ @@CȀ # Pushing it again will turn off sampling, and display the results (SPY.TREE 10). This is the simplest way of spying on operations. (Note that you can't turn off sampling if the mouse process is locked out.) Alternatively, you can turn Spying on and off by using the following functions: (SPY.START) [Function] Reinitializes the internal Spy data structures, and turns on sampling. (SPY.END) [Function] Turns off sampling, and cleans up the data structures. (SPY.TOGGLE) [Function] If Spying is off, turn it on with (SPY.START). If it's on, turn it off with (SPY.END) and then show the results with (SPY.TREE 10). It's reasonable to use this as an interrupt character, e.g., (INTERRUPTCHAR (CHARCODE ^C) '(SPY.TOGGLE) T) will enable control-C as an interrupt which will turn spying on and off same as pushing the spy button. (WITH.SPY form) [Macro] Calls (SPY.START), evaluates form, calls (SPY.END), and then returns the value of form. For example, (WITH.SPY (LOAD 'FOO)) is basically (PROGN (SPY.START) (PROG1 (LOAD 'FOO) (SPY.END]. To display the results, call the function SPY.TREE: (SPY.TREE threshold individualp mergetype depthlimit) [Function] SPY.TREE displays the results of the last spy'' in a grapher window. There are a number of parameters that control the display, which you can either set when you call SPY.TREE, or set interactively with the menu. I normally just use (SPY.TREE) and use the menus. threshold is a number (defaults to 0), individualp is either NIL or T, mergetype is one of (NONE, ALL, DEFAULT), and depthlimit is a number (defaults to NIL = arbitrary depth; not completely debugged for other values). You will get a prompt to lay down a window, and then a graph will appear in it, something like this: x?u_w]Wsu?w]Ommvw]qwWw]imwVxbxCq @$ JR $ JP @ 8rP (RP?? $JR?? I 0000  0000 0000 0000! 0000! 0000@ 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 & 0000  0000@ 0000@ 0000B,<q 0000 Cr JR 0000 # JP  0000@"8rP 0000 RP 0000 2JR 0000! ,cH 000b @ JP"H 000 w1a"O000000 000` 000000000 0000000`` 0F0$c<01E"L$Ir`` 0Hܥ(R)03% D R$J `` 0KXR!01-`DP$J0`` 0Mh875T L