Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | CallGraph |
2 | ========= | |
3 | ||
4 | For easier visualization of <:Profiling:profiling> data, `mlprof` can | |
5 | create a call graph of the program in dot format, from which you can | |
6 | use the http://www.research.att.com/sw/tools/graphviz/[graphviz] | |
7 | software package to create a PostScript or PNG graph. For example, | |
8 | ---- | |
9 | mlprof -call-graph foo.dot foo mlmon.out | |
10 | ---- | |
11 | will create `foo.dot` with a complete call graph. For each source | |
12 | function, there will be one node in the graph that contains the | |
13 | function name (and source position with `-show-line true`), as | |
14 | well as the percentage of ticks. If you want to create a call graph | |
15 | for your program without any profiling data, you can simply call | |
16 | `mlprof` without any `mlmon.out` files, as in | |
17 | ---- | |
18 | mlprof -call-graph foo.dot foo | |
19 | ---- | |
20 | ||
21 | Because SML has higher-order functions, the call graph is is dependent | |
22 | on MLton's analysis of which functions call each other. This analysis | |
23 | depends on many implementation details and might display spurious | |
24 | edges that a human could conclude are impossible. However, in | |
25 | practice, the call graphs tend to be very accurate. | |
26 | ||
27 | Because call graphs can get big, `mlprof` provides the `-keep` option | |
28 | to specify the nodes that you would like to see. This option also | |
29 | controls which functions appear in the table that `mlprof` prints. | |
30 | The argument to `-keep` is an expression describing a set of source | |
31 | functions (i.e. graph nodes). The expression _e_ should be of the | |
32 | following form. | |
33 | ||
34 | * ++all++ | |
35 | * ++"__s__"++ | |
36 | * ++(and __e ...__)++ | |
37 | * ++(from __e__)++ | |
38 | * ++(not __e__)++ | |
39 | * ++(or __e__)++ | |
40 | * ++(pred __e__)++ | |
41 | * ++(succ __e__)++ | |
42 | * ++(thresh __x__)++ | |
43 | * ++(thresh-gc __x__)++ | |
44 | * ++(thresh-stack __x__)++ | |
45 | * ++(to __e__)++ | |
46 | ||
47 | In the grammar, ++all++ denotes the set of all nodes. ++"__s__"++ is | |
48 | a regular expression denoting the set of functions whose name | |
49 | (followed by a space and the source position) has a prefix matching | |
50 | the regexp. The `and`, `not`, and `or` expressions denote | |
51 | intersection, complement, and union, respectively. The `pred` and | |
52 | `succ` expressions add the set of immediate predecessors or successors | |
53 | to their argument, respectively. The `from` and `to` expressions | |
54 | denote the set of nodes that have paths from or to the set of nodes | |
55 | denoted by their arguments, respectively. Finally, `thresh`, | |
56 | `thresh-gc`, and `thresh-stack` denote the set of nodes whose | |
57 | percentage of ticks, gc ticks, or stack ticks, respectively, is | |
58 | greater than or equal to the real number _x_. | |
59 | ||
60 | For example, if you want to see the entire call graph for a program, | |
61 | you can use `-keep all` (this is the default). If you want to see | |
62 | all nodes reachable from function `foo` in your program, you would | |
63 | use `-keep '(from "foo")'`. Or, if you want to see all the | |
64 | functions defined in subdirectory `bar` of your project that used | |
65 | at least 1% of the ticks, you would use | |
66 | ---- | |
67 | -keep '(and ".*/bar/" (thresh 1.0))' | |
68 | ---- | |
69 | To see all functions with ticks above a threshold, you can also use | |
70 | `-thresh x`, which is an abbreviation for `-keep '(thresh x)'`. You | |
71 | can not use multiple `-keep` arguments or both `-keep` and `-thresh`. | |
72 | When you use `-keep` to display a subset of the functions, `mlprof` | |
73 | will add dashed edges to the call graph to indicate a path in the | |
74 | original call graph from one function to another. | |
75 | ||
76 | When compiling with `-profile-stack true`, you can use `mlprof -gray | |
77 | true` to make the nodes darker or lighter depending on whether their | |
78 | stack percentage is higher or lower. | |
79 | ||
80 | MLton's optimizer may duplicate source functions for any of a number | |
81 | of reasons (functor duplication, monomorphisation, polyvariance, | |
82 | inlining). By default, all duplicates of a function are treated as | |
83 | one. If you would like to treat the duplicates separately, you can | |
84 | use ++mlprof -split __regexp__++, which will cause all duplicates of | |
85 | functions whose name has a prefix matching the regular expression to | |
86 | be treated separately. This can be especially useful for higher-order | |
87 | utility functions like `General.o`. | |
88 | ||
89 | == Caveats == | |
90 | ||
91 | Technically speaking, `mlprof` produces a call-stack graph rather than | |
92 | a call graph, because it describes the set of possible call stacks. | |
93 | The difference is in how tail calls are displayed. For example if `f` | |
94 | nontail calls `g` and `g` tail calls `h`, then the call-stack graph | |
95 | has edges from `f` to `g` and `f` to `h`, while the call graph has | |
96 | edges from `f` to `g` and `g` to `h`. That is, a tail call from `g` | |
97 | to `h` removes `g` from the call stack and replaces it with `h`. |