/************************************************************************* * * * YAP Prolog * * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: callcount.yap * * Last rev: 8/2/02 * * mods: * * comments: Some profiling predicates available in yap * * * *************************************************************************/ %% @{ /** @defgroup Profiling Profiling Prolog Programs @ingroup extensions YAP includes two profilers. The count profiler keeps information on the number of times a predicate was called. This information can be used to detect what are the most commonly called predicates in the program. The count profiler can be compiled by setting YAP's flag profiling to `on`. The time-profiler is a `gprof` profiler, and counts how many ticks are being spent on specific predicates, or on other system functions such as internal data-base accesses or garbage collects. The YAP profiling sub-system is currently under development. Functionality for this sub-system will increase with newer implementation. */ %% @{ /** @defgroup Call_Counting Counting Calls @ingroup Profiling Predicates compiled with YAP's flag call_counting set to `on` update counters on the numbers of calls and of retries. Counters are actually decreasing counters, so that they can be used as timers. Three counters are available: + `calls`: number of predicate calls since execution started or since system was reset; + `retries`: number of retries for predicates called since execution started or since counters were reset; + `calls_and_retries`: count both on predicate calls and retries. These counters can be used to find out how many calls a certain goal takes to execute. They can also be used as timers. The code for the call counters piggybacks on the profiling code. Therefore, activating the call counters also activates the profiling counters. These are the predicates that access and manipulate the call counters. */ :- system_module( '$_callcount', [call_count/3, call_count_data/3, call_count_reset/0], []). :- use_system_module( '$_errors', ['$do_error'/2]). /** @pred call_count_data(- _Calls_, - _Retries_, - _CallsAndRetries_) Give current call count data. The first argument gives the current value for the _Calls_ counter, next the _Retries_ counter, and last the _CallsAndRetries_ counter. */ call_count_data(Calls, Retries, Both) :- '$call_count_info'(Calls, Retries, Both). /** @pred call_count_reset Reset call count counters. All timers are also reset. */ call_count_reset :- '$call_count_reset'. /** @pred call_count(? _CallsMax_, ? _RetriesMax_, ? _CallsAndRetriesMax_) Set call counters as timers. YAP will generate an exception if one of the instantiated call counters decreases to 0: + _CallsMax_ throw the exception `call_counter` when the counter `calls` reaches 0; + _RetriesMax_ throw the exception `retry_counter` when the counter `retries` reaches 0; + _CallsAndRetriesMax_ throw the exception `call_and_retry_counter` when the counter `calls_and_retries` reaches 0. YAP will ignore counters that are called with unbound arguments. Next, we show a simple example of how to use call counters: ~~~~~{.prolog} ?- yap_flag(call_counting,on), [-user]. l :- l. end_of_file. yap_flag(call_counting,off). yes yes ?- catch((call_count(10000,_,_),l),call_counter,format("limit_exceeded.~n",[])). limit_exceeded. yes ~~~~~ Notice that we first compile the looping predicate `l/0` with call_counting `on`. Next, we catch/3 to handle an exception when `l/0` performs more than 10000 reductions. */ call_count(Calls, Retries, Both) :- '$check_if_call_count_on'(Calls, CallsOn), '$check_if_call_count_on'(Retries, RetriesOn), '$check_if_call_count_on'(Both, BothOn), '$call_count_set'(Calls, CallsOn, Retries, RetriesOn, Both, BothOn). '$check_if_call_count_on'(Calls, 1) :- integer(Calls), !. '$check_if_call_count_on'(Calls, 0) :- var(Calls), !. '$check_if_call_count_on'(Calls, A) :- '$do_error'(type_error(integer,Calls),call_count(A)). %% @} /** @} */