Anubis Profiling¶
Profiling functionnalities have been added to Anubis 1.8.
Documentation¶
To use them, you first have to compile your ADM with the profiling instructions, using -profile option into the command line. A good idea is to use the -sc option to, as it can help you to identify the different functions and their location into source code.
Once compiled, you just have to start your ADM with the VirtualMachine. At the end of the execution (you can use CTRL + C to end your ADM), the VM will output (on stderr) plain text information about profiling. On big software, that a good idea to redirect stderr to a file (using '2> filename' on command line).
Some options are available to format the output :-profile:csv | Use CSV (Comma Separated Values) output insteed of plain text | |||
-csv_sep:<sep> | Allows to define a separator for CSV output (ex: '-csv_sep:;' to have a semi-colon insteed a comma) |
Examples¶
Plain text output for fibonnacci.anubis
Command line : anbexec fib 29
*** PROFILING DATA *** *** Full executing time = 10.362 s Function fib() [offset = 541]: hits = 1 time (excluding children) = 0.002 s (0.0%) max (including children) = 10.361 s (100.0%) Function fib() [offset = 173]: hits = 1664079 time (excluding children) = 10.360 s (100.0%) max (including children) = 10.360 s (100.0%) Function +() [offset = 89]: hits = 1 time (excluding children) = 0.000 s (0.0%) max (including children) = 0.000 s (0.0%)
CSV output for fibonnacci.anubis
Command line : anbexec fib 29 --profile:csvFunction | Offset | Hits | Time (excl. children) | Time % | Max (inc. children) | Max % | ||||||||
fib | 541 | 1 | 0.001657 | 0.0 | 10.623458 | 100.0 | ||||||||
fib | 173 | 1664079 | 10.621774 | 100.0 | 10.621774 | 100.0 | ||||||||
+ | 89 | 1 | 0.000027 | 0.0 | 0.000027 | 0.0 |
About Terminal Calls¶
Terminal calls can be a problem for profiling.
First, they can't be representated by recursive calls because we can have an infinite succession of these calls.
Other approach is to do a 'fake' return just before a TerminalCall. But resulting profiling information is not really usable because the calls arborescence is broken.
So the choosen approach was to consider that all subsequent TerminalCalls made from a function are simply like if this was the same function. Helped by some examples, I will try to show you how it works.
1. [[TerminalCall]] used as loop
If a terminal call is used as a loop implementation, this strategy is really fine because the function will be seen as if it was called only once and its execution time will include all loop interations.
2. [[TerminalCall]] used as automate
For the automate, profiling data are incomplete but not so bad... Only the automate entry function will be seen, but its execution time will include all subsequent calls into the automate. So we can have the automate executing time, but not the details of the functions composing it.
3. Functions that are simply terminating by a [[TerminalCall]] to another function.
In this case, the second fonction will not be seen and it execution time will be include into its caller. So some fonction can never appear because the compiler have otimized its call to a [[TerminalCall]]. This is the worse case because some functions were hidden.
Example:
global define One fib ( List(String) args ) = if args is { [ ] then print("Usage: fib <interger>\n"), [h . t] then if string_to_integer(h) is { failure then print("Argument must be a integer.\n"), success(n) then print("Fib("+h+") = " + fib(n) + "\n") } }.
The print() function will never appear on profiling data because it's always used as TerminalCall of the fib() function. So its executing time will be included to the fib() function.