- defined_modules(+File, -Modules)
- Retrieve the modules defined by a file.
- erase_all_templates
- Erase all instrument template stores.
- erase_file_templates(+File)
- Erase the file local instrument template store for a specific file.
- erase_module_templates
- Erase all instrument template stores for a specific module.
- file_callsites(+File, ?StartId, ?EndId)
- Retrieve start and end callsite identifiers for named file.
- file_result(+File)
- Pretty-print a file, including any instrumentation results
- file_result(+File, +OptionList)
- Pretty-print a file, including any instrumentation results
- get_callsite_data(+SiteId, ?UserData)
- Retrieve data associated with an instrumentation callsite from its non-logical store.
- instrument(+File, +ITemplates)
- Compile a file, inserting predicate instrumentation
- instrument(+File, +ITemplates, +OptionList)
- Compile a file, inserting predicate instrumentation
- instrument_control(+Mode, +InstrumentPredSpec)
- Insert or remove instrumentation predicates dynamically at runtime.
- module_callsites(?StartId, ?EndId)
- Retrieve module start and end callsite identifiers.
- module_result
- Pretty-print all files in a module, including any instrumentation results
- module_result(+OptionList)
- Pretty-print all files in a module, including any instrumentation results
- set_callsite_data(+SiteId, ?UserData)
- Associate arbitrary data with an instrumentation callsite in a non-logical store.
- struct itemplate(clause_start, clause_end, clause_fail, clause_redo, block_start, block_end, block_fail, block_redo, subgoal_start, subgoal_end, subgoal_fail, subgoal_redo, call_start, call_end, call_fail, call_redo, fact, inbetween, result, meta_args, exclude, code_weaver, asserted, module_scope, file_local, goal_expansion)
- The template used to guide predicate instrumentation
The instrument library is a tool that enables predicate definitions or all calls to a specific predicate to be annotated with user-defined predicates. These instrumentation predicates are free to perform such actions as collect program statistics or write debugging data to a stream during program execution. Additionally, the instrumentation can be inserted and removed dynamically as the program executes.
The usage is as follows:
?- lib(instrument).
?- instrument:instrument(my_program, Templates).
?- my_query(X,Y,Z).
?- instrument:results(my_program).
The following is an example of very basic use of the tool. Consider instrumenting a simple path finding program saved in a file called 'instrument_example.ecl.
list_member(X, [X | _Tail]). list_member(X, [_ | Tail]):- list_member(X, Tail). all_edges(Graph, Source, Outgoing):- findall((Source-Next),list_member((Source-Next), Graph), Outgoing). path(_Graph, Source, Source, []). path(Graph, Source, Sink, [(Source-Next) | Path]):- all_edges(Graph, Source, Outgoing), list_member((Source-Next), Outgoing), path(Graph, Next, Sink, Path). test(Path):- path([1-2, 1-3, 2-4, 3-4, 4-5, 4-6, 5-7, 5-8, 6-7, 1-8, 8-9, 8-10, 9-10, 9-11, 10-11], 1, 7, Path).The simplest way to instrument your code is to insert predicates around every call in the source. The following code demonstrates how to print the CPU time before and after every predicate call:
get_time(Cpu):- statistics(times, [Cpu, _Sys, _Real]). time_point:- get_time(T), writeln(error, T). go:- File = instrument_example, GlobalTemplate = itemplate{subgoal_start:time_point/0, subgoal_end:time_point/0}, instrument(File, GlobalTemplate), test(Path).Note the same predicate time_point/0 is specified before and after goal calls. If we wished to instrument all calls except those to list_member/2, the following call to instrument/2 is made:
instrument(File, GlobalTemplate - [list_member/2])In general any number of goals may be specified in this 'exclusion list'.
The following code demonstrates alternative instrumentation for this excluded predicate:
:-lib(instrument). :-export time_point/0, special_point/0. get_time(Cpu):- statistics(times,[Cpu, _Sys, _Real]). time_point:- get_time(T), writeln(error, T). special_point:- writeln(error, 'start, end, redo or fail'). go:- File = instrument_example, GlobalTemplate = itemplate{subgoal_start:time_point/0, subgoal_end:time_point/0}, SpecialTemplate = itemplate{call_start:special_point/0, call_end:special_point/0, call_fail:special_point/0 call_redo:special_point/0}, instrument(File,[GlobalTemplate - [list_member/2], (list_member/2) = SpecialTemplate]), test(Path).Notice how the special_point/0 predicate is assigned to the call_start, call_end, call_fail and call_redo points in this example. This ensures that the special_point predicate is called if list_member/2 fails, or if resatisfiable, executed at the redo.
Using arity-1 predicates (i.e. one argument predicates) unique identification of the callsite can be obtained:
:-lib(instrument). get_time(Cpu):- statistics(times, [Cpu, _Sys, _Real]). time_point(CallSite):- get_time(T), writeln(error,['Time', T, 'at callsite', CallSite]). go:- File = instrument_example, GlobalTemplate = itemplate{subgoal_start:time_point/1, subgoal_end:time_point/1}, instrument(File, GlobalTemplate), test(Path).
By supplying a predicate to the result field of a template one can specify terms to be printed within a copy of the source code. Using this feature along with the utility predicates get_callsite_data/2 and set_callsite_data/2 one can create quite varied and useful output.
:-lib(instrument). get_time(Cpu):- statistics(times, [Cpu, _Sys, _Real]). time_point(CallSite):- get_time(T), set_callsite_data(CallSite, T). result(CallSite, _Type, _Module, Goal, NewGoal):- get_callsite_data(CallSite, Time), NewGoal='instrument:point_before'(Time, Goal). go:- File = instrument_example, GlobalTemplate = itemplate{subgoal_start:time_point/1, result:result/5}, instrument(File, GlobalTemplate), test(Path), file_result(File).No data is printed during the running of the test(Path) call, but the file_result(File) call causes the source code to be emitted (color coded) with the given callsite data embedded.