1% BEGIN LICENSE BLOCK 2% Version: CMPL 1.1 3% 4% The contents of this file are subject to the Cisco-style Mozilla Public 5% License Version 1.1 (the "License"); you may not use this file except 6% in compliance with the License. You may obtain a copy of the License 7% at www.eclipse-clp.org/license. 8% 9% Software distributed under the License is distributed on an "AS IS" 10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11% the License for the specific language governing rights and limitations 12% under the License. 13% 14% The Original Code is The ECLiPSe Constraint Logic Programming System. 15% The Initial Developer of the Original Code is Cisco Systems, Inc. 16% Portions created by the Initial Developer are 17% Copyright (C) 1995 - 2006 Cisco Systems, Inc. All Rights Reserved. 18% 19% Contributor(s): 20% 21% END LICENSE BLOCK 22% 23% @(#)umsprofile.tex 1.4 95/03/17 24% 25% 26% umsprofile.tex 27% 28% REL DATE AUTHOR DESCRIPTION 29% 8.5.90 Joachim Schimpf based on relase notes 2.3 30% 31 32\chapter{Profiling Prolog Execution} 33\label{chapprofile} 34\index{profiling} 35 36%\section{Introduction} 37%{\eclipse} contains two profiling tools that permit to collect statistics 38%about the execution of a Prolog program. 39%This information can be used to 40%\begin{itemize}{}{\itemsep 1cm} 41%\item find "hot spots" in a program that are worth optimising 42%\item reveal unexpected behaviour of predicates (e.g. backtracking) 43%\item provide mode declarations for the program 44%\end{itemize} 45%The first tool is the {\it profiler} which finds out how much time 46%was spent in which procedure, 47%the second tool is the {\it statistics} tool which collects 48%for each called predicate the statistics about its behaviour 49%during the program. 50 51%\section{Using the Profiling Tool} 52The profiling tool\footnote{% 53 The profiler requires a small amount of 54 hardware/compiler dependent code and may therefore not be available on 55 all platforms.} 56helps to find "hot spots" in a program that are worth optimising. 57It can be used any time with any compiled Prolog code, 58it is not necessary to use a special compilation mode or set 59any flags. 60When 61\begin{quote} 62:- profile(Goal). 63\end{quote} 64is called, the profiler executes the {\it Goal} in the profiling mode, 65which means that every 0.01s the execution is interrupted 66and the profiler remembers the currently executing procedure. 67When the goal succeeds or fails, the profiler prints so 68and then it prints the statistics about the time spent 69in every encountered procedure: 70 71\begin{quote} 72\begin{verbatim} 73 74[eclipse 5]: profile(boyer). 75rewriting... 76proving... 77goal succeeded 78 79 PROFILING STATISTICS 80 -------------------- 81 82Goal: boyer 83Total user time: 10.65s 84 85Predicate Module %Time Time 86------------------------------------------------- 87rewrite /2 eclipse 52.3% 5.57s 88garbage_collect /0 sepia_kernel 23.1% 2.46s 89rewrite_args /2 eclipse 16.6% 1.77s 90equal /2 eclipse 4.7% 0.50s 91remainder /3 eclipse 1.5% 0.16s 92... 93plus /3 eclipse 0.1% 0.01s 94 95yes. 96\end{verbatim} 97\end{quote} 98 99The profiler prints the predicate name and arity, its definition module, 100percentage of total time spent in this predicate and the absolute time. 101Some of auxiliary system predicates are printed under a 102common name without arity, e.g. {\it arithmetic} or {\it all_solutions}. 103Predicates which are local to locked modules are printed 104together on one line that contains only the module name. 105By default only predicates written in Prolog are profiled, i.e. 106if a Prolog predicate calls an external or built-in predicate 107written in C, the time will be assigned to the Prolog predicate. 108 109The predicate {\bf profile(Goal, Flags)} can be used to change 110the way profiling is made, {\it Flags} is a list of flags. 111Currently only the flag {\tt simple} is accepted and it 112causes separate profiling of simple predicates, i.e. 113those written in C: 114 115\begin{quote} 116\begin{verbatim} 117[eclipse 6]: profile(boyer, [simple]). 118rewriting... 119proving... 120goal succeeded 121 122 PROFILING STATISTICS 123 -------------------- 124 125Goal: boyer 126Total user time: 10.55s 127 128Predicate Module %Time Time 129------------------------------------------------- 130=.. /2 sepia_kernel 31.1% 3.28s 131garbage_collect /0 sepia_kernel 23.5% 2.48s 132rewrite /2 eclipse 21.6% 2.28s 133rewrite_args /2 eclipse 17.2% 1.82s 134equal /2 eclipse 4.1% 0.43s 135remainder /3 eclipse 0.9% 0.10s 136... 137plus /3 eclipse 0.1% 0.01s 138 139yes. 140\end{verbatim} 141\end{quote} 142 143 144%\section{Using the Statistics Facility} 145%The statistics tool is predicate based. 146%The user can switch on statistics collection 147%for all predicates or for selected ones. 148% 149%The statistics tool is closely related to the debugger. 150%In order to apply it to a program, this program must be 151%compiled in {\bf dbgcomp}-mode and it must be run with the debugger 152%switched on. 153% 154%\noindent 155%A sample output from the statistics tool looks like this: 156%\begin{verbatim} 157% PROCEDURE # MODULE #CALL #EXIT #TRY #CUT #NEXT #FAIL 158%true /0 sepia_k 2 2 0 0 0 0 159%fail /0 sepia_k 27 0 0 0 0 27 160%set_flag /3 sepia_k 1 1 0 0 0 0 161%env /0 sepia_k 1 1 1 0 2 0 162%spaces /1 sepia_k 309 309 309 286 23 0 163%! /0 sepia_k 286 286 0 0 0 0 164%open /3 sepia_k 1 1 0 0 0 0 165%|TOTAL: PROCEDURES: 7 627 600 310 286 25 27 166%\end{verbatim} 167% 168%The numbers show how often the execution passed the various predicate ports 169%(for a description of the ports see \ref{chapdebug}). 170%In coroutine mode the table has 2 more columns for DELAY and WAKE ports. 171%The relation between the debugger ports and the statistics counters is as 172%follows: 173% 174%\begin{description} 175%\item [CALL -] counts CALL ports 176%\item [EXIT -] counts EXIT and *EXIT ports 177%\item [TRY -] there is no corresponding port, it stands for entering the 178%first of several matching clauses or a disjunction (choicepoint creation) 179%\item [CUT -] counts CUT ports 180%\item [NEXT -] counts NEXT ports 181%\item [FAIL -] counts FAIL and *FAIL ports 182%\item [DELAY -] counts DELAY ports (in coroutine mode only) 183%\item [WAKE -] counts WAKE ports (in coroutine mode only) 184%\end{description} 185% 186%\noindent 187%Ports that can not be displayed by the debugger are not available for 188%the statistics tool either, ie. 189%\begin{itemize} 190%\item subgoals of predicates that are set to {\tt skipped} (user predicates 191%are not skipped by default) 192%\item subgoals of predicates that are compiled in {\bf nodbgcomp}-mode 193%\item untraceable predicates (user predicates and all built-ins are 194%traceable by default) 195%\end{itemize} 196% 197%\noindent 198%There is a global flag {\tt statistics} (accessed with \bipref{set_flag/2}{../bips/kernel/env/set_flag-2.html}, 199%\bipref{get_flag/2}{../bips/kernel/env/get_flag-2.html}) that can take four possible values: 200%\begin{itemize} 201%\item {\bf off} - no procedure is counted 202%\item {\bf some} - some specified (using \bipref{set_flag/3}{../bips/kernel/compiler/set_flag-3.html} or 203%\bipref{set_statistics/2}{../bips/kernel/obsolete/set_statistics-2.html}) procedures are counted 204%\item {\bf all} - all traceable procedures are counted 205%\item {\bf mode} - like {\bf all}, but the mode usage is also collected 206%\end{itemize} 207% 208%The output of the statistics tool goes to the {\tt output} stream. 209%Most of the time it is useful to write it into a file using 210%\begin{quote}\begin{verbatim} 211%?- open(table, write, output), print_statistics, close(output). 212%\end{verbatim}\end{quote} 213%where it can be further processed. 214%The statistics table can be sorted on a specified column 215%with the Unix {\it sort(2)} command, e.g. 216%\begin{quote}\begin{verbatim} 217%sort -n -r +4 table 218%\end{verbatim}\end{quote} 219%will sort with procedures that exited most frequently first. 220% 221%To improve the performance of a program, the following 222%considerations might apply: 223% 224%\begin{itemize} 225%\item The {\bf CALL} ports show how often a procedure is called 226%and hence procedures with many CALLS are crucial to the program's 227%performance. 228% 229%\item Many {\bf TRY} ports show that either the procedure 230%is really nondeterministic, or that it is written in such a manner 231%that the compiler cannot decide which clause will match a given 232%call and so it has to create a choice point and try several clauses 233%in sequence. 234% 235%\item {\bf NEXT} ports mean most often that the compiler did not 236%succeed to pick up the right clause at the first try 237%and so another one had to be tried. 238%Rewriting the procedure might help, as well as providing mode 239%declarations. 240% 241%\item If there are much less {\bf CUT} ports than {\bf CALL} ports 242%of the procedure \bipref{!/0}{../bips/kernel/control/I-0.html}, it means that some cuts in 243%the program source are redundant. 244%\end{itemize} 245% 246%\subsection{Exhaustive Collection} 247%To get a complete statistic about a program execution, ie. to collect 248%information about all predicates executed, the global {\tt statistics}-flag 249%is used. A sample session follows: 250%\begin{verbatim} 251%[eclipse 1]: [qsort]. % compile (in dbgcomp mode !) 252%/.../qsort.pl compiled 2708 bytes in 0.02 seconds 253% 254%yes. 255%[eclipse 2]: set_flag(statistics, all). % switch collecting on 256% 257%yes. 258%[eclipse 3]: debug(go_qsort). % run program under debugger control 259%Start debugging - leap mode 260%Stop debugging. 261% 262%yes. 263%[eclipse 4]: print_statistics. % print the results 264% PROCEDURE # MODULE #CALL #EXIT #TRY #CUT #NEXT #FAIL 265%go_qsort /0 eclipse 1 1 0 0 0 0 266%list50 /1 eclipse 1 1 0 0 0 0 267%qsort /3 eclipse 101 101 0 0 0 0 268%partition /4 eclipse 275 275 225 103 122 0 269%=< /2 sepia_k 225 103 0 0 0 122 270%! /0 sepia_k 103 103 0 0 0 0 271%|TOTAL: PROCEDURES: 6 706 584 225 103 122 122 272% 273%yes. 274%\end{verbatim} 275%By redirecting the {\tt output} stream the table can be printed into a file. 276%It can then be easily sorted and printed. 277% 278%Calling {\tt set_flag(statistics, all)} again will reset all counters to zero, 279%\newline 280%{\tt set_flag(statistics, off)} will reset all counters to zero and 281%disable further statistics. 282%The current value of the global {\tt statistics}-flag can be queried with 283%\bipref{get_flag/2}{../bips/kernel/env/get_flag-2.html} or \bipref{env/0}{../bips/kernel/env/env-0.html}. 284% 285%Counter values of individual predicates can be retrieved using 286%the built-in \bipref{get_statistics/2}{../bips/kernel/obsolete/get_statistics-2.html}. It returns an 8-element-list of the 287%counters in the same order as displayed by \bipref{print_statistics/0}{../bips/kernel/obsolete/print_statistics-0.html} 288%(ie. \#CALL, \#EXIT, \#TRY, \#CUT, \#NEXT, \#FAIL, \#DELAY, \#WAKE). 289%\begin{verbatim} 290%[eclipse 1]: get_statistics(partition/4, Counters). 291% 292%Counters = [275, 275, 225, 103, 122, 0, 0, 0] 293%yes. 294%\end{verbatim} 295%There is also a corresponding built-in \bipref{set_statistics/2}{../bips/kernel/obsolete/set_statistics-2.html} that allows 296%initialising the counters. It can be used for collecting cumulative statistics. 297% 298%\subsection{Selective Collection} 299%It is possible to collect statistic information only for some 300%specified predicates. 301%For that purpose, every predicate has an individual {\tt statistics}-flag. 302%A predicate is selected for statistics by switching this flag to {\tt on}, 303%using: 304%\begin{verbatim} 305%set_flag(PredSpec, statistics, on). 306%\end{verbatim} 307%This will also initialise the predicate's counters to zero. 308%Initialising the predicate's counters using \bipref{set_statistics/2}{../bips/kernel/obsolete/set_statistics-2.html} will also 309%select this predicate for statistics and set its {\tt statistics}-flag. 310%In both cases, the global flag will change to {\tt some}, provided its 311%old value was not {\tt all}. 312%\begin{verbatim} 313%[eclipse 1]: set_flag(statistics, off). % reset all counters 314% 315%yes. 316%[eclipse 2]: set_flag(partition/4, statistics, on), 317% set_flag(qsort/3, statistics, on). % select some predicates 318% 319%yes. 320%[eclipse 3]: get_flag(statistics, X). 321% 322%X = some 323%yes. 324%[eclipse 4]: debug(go_qsort). % run program under debugger control 325%Start debugging - leap mode 326%Stop debugging. 327% 328%yes. 329%[eclipse 5]: print_statistics. % print the results 330% PROCEDURE # MODULE #CALL #EXIT #TRY #CUT #NEXT #FAIL 331%partition /4 eclipse 275 275 225 103 122 0 332%qsort /3 eclipse 101 101 0 0 0 0 333%|TOTAL: PROCEDURES: 2 376 376 225 103 122 0 334% 335%yes. 336%\end{verbatim} 337% 338%\subsection{Obtaining mode information} 339%\index{mode/1} 340%\index{mode statistics} 341%The global {\tt statistics}-flag can take another value called {\tt mode}. 342%This has the same effect as {\tt all}, but in addition there is 343%information collected about the actual arguments of predicate calls. 344%The arguments are tested for being instantiated and for groundness. 345%This information is helpful to provide mode declarations for 346%a program. 347%The results are displayed by the {\tt print_modes/0} built-in in the form 348%of a mode declaration summarising the information that could be extracted 349%from the predicate calls executed. 350%The output is in the form of a mode declaration that can be read in and 351%executed. 352%\begin{verbatim} 353%[eclipse 1]: set_flag(statistics,mode). 354% 355%yes. 356%[eclipse 2]: debug(go_qsort). 357%Start debugging - leap mode 358%Stop debugging. 359% 360%yes. 361%[eclipse 3]: print_modes. 362%:- mode 363% list50(-), 364% qsort(++, -, ++), 365% partition(++, ++, -, -). 366% 367%yes. 368%\end{verbatim} 369%Note that these modes are not the result of a program analysis. 370%They just indicate what arguments occurred in the sample run of the program. 371%Hence it may well be that running the program with different data 372%produces a different mode statistics. 373% 374%If a procedure has already an explicit mode declaration, the modes 375%returned by the mode statistics will not be more restrictive than the 376%declaration, e.g. if a declaration 377%\begin{verbatim} 378%:- mode p(+). 379%\end{verbatim} 380%exists and {\bf p/1} is called with a ground argument only, the generated 381%mode will be {\bf +} rather than {\bf ++}. 382% 383