153 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			4.2 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		 *
 | 
						|
*									 *
 | 
						|
*************************************************************************/
 | 
						|
 | 
						|
%% @{
 | 
						|
 | 
						|
/** @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)).
 | 
						|
 | 
						|
%% @}
 | 
						|
 | 
						|
/**
 | 
						|
@}
 | 
						|
*/
 | 
						|
 |