157 lines
4.3 KiB
Prolog
157 lines
4.3 KiB
Prolog
/*************************************************************************
|
|
* *
|
|
* 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 *
|
|
* *
|
|
*************************************************************************/
|
|
|
|
%% @{
|
|
|
|
/**
|
|
@file callcount.yap
|
|
@short support call counting.
|
|
|
|
@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)).
|
|
|
|
%% @}
|
|
|
|
/**
|
|
@}
|
|
*/
|
|
|