This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/pl/callcount.yap

157 lines
4.5 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
* @brief the clock and the tick profilers.
* @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.
*
* + Call_Counting
* +
*
*/
/**
@}
*/
/**
* @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)).
%% @}