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) 2006 Cisco Systems, Inc. All Rights Reserved. 18% 19% Contributor(s): 20% 21% END LICENSE BLOCK 22 23%---------------------------------------------------------------------- 24\chapter{Program Analysis} 25\label{sec:program-analysis} 26\index{program analysis|(} 27%HEVEA\cutdef[1]{section} 28%---------------------------------------------------------------------- 29 30This chapter describes some of the tools provided by \eclipse{} to 31analyse the runtime behaviour of a program. 32\index{performance}\index{optimisation} 33%---------------------------------------------------------------------- 34\section{What tools are available?} 35%---------------------------------------------------------------------- 36 37\eclipse{} provides a number of different tools to help the programmer 38understand their how their program behaves at runtime. 39 40\quickrefstatic{Available Program Analysis tools}{ 41\begin{small} 42\begin{description} 43\item[Debugger] Provides a low level view of program 44activity. \See{See chapter~\ref{chapdebug} and the \emph{Debugging} 45section in the user manual for a comprehensive look at debugging 46\eclipse{} programs} 47\item[Profiler] Samples the running program at regular intervals to 48give a statistical summary of where the execution time is spent. 49\item[Port Profiler] Collects statistics about program execution in terms 50of the box model of execution. See library(port_profiler) or use the 51\emph{Port Profile} option from the tkeclipse \emph{Run} menu. 52\item[Coverage] Records the number of times various parts of the 53program are executed. 54\item[Visualisation framework] \See{See the \emph{Visualisation Tools Manual} for more information} 55\end{description} 56\end{small} 57} 58 59This section focuses on two complementary tools 60\begin{enumerate} 61\item The \emph{profiler} 62\item The \emph{coverage} library 63\end{enumerate} 64 65%---------------------------------------------------------------------- 66\section{Profiler} 67%---------------------------------------------------------------------- 68 69\index{profiling} The profiling tool helps to find \emph{hot spots} in 70a program that are worth optimising. It can be used any time with any 71compiled Prolog code, it is not necessary to use a special compilation 72mode or set any flags. Note however that it is not available on 73Windows\index{windows}. When 74\begin{quote}\begin{verbatim} 75?- profile(Goal). 76\end{verbatim}\end{quote} 77\index{profile/1} is called, the profiler executes the \emph{Goal} in 78the profiling mode, which means that every 100th of a second the 79execution is interrupted and the profiler records the currently 80executing procedure. 81 82Consider the following \textbf{n-queens} code. 83\begin{code} 84queen(Data, Out) :- 85 qperm(Data, Out), 86 safe(Out). 87 88qperm([], []). 89qperm([X|Y], [U|V]) :- 90 qdelete(U, X, Y, Z), 91 qperm(Z, V). 92 93qdelete(A, A, L, L). 94qdelete(X, A, [H|T], [A|R]) :- 95 qdelete(X, H, T, R). 96 97safe([]). 98safe([N|L]) :- 99 nodiag(L, N, 1), 100 safe(L). 101 102nodiag([], _, _). 103nodiag([N|L], B, D) :- 104 D =\verb+\+= N - B, 105 D =\verb+\+= B - N, 106 D1 is D + 1, 107 nodiag(L, B, D1). 108\end{code} 109 110Issuing the following query will result in the profiler recording the 111currently executing goal 100 times a second. 112 113\begin{quote}\begin{verbatim} 114?- profile(queen([1,2,3,4,5,6,7,8,9],Out)). 115goal succeeded 116 117 PROFILING STATISTICS 118 -------------------- 119 120Goal: queen([1, 2, 3, 4, 5, 6, 7, 8, 9], Out) 121Total user time: 0.03s 122 123Predicate Module %Time Time %Cum 124-------------------------------------------------------- 125qdelete /4 eclipse 50.0% 0.01s 50.0% 126nodiag /3 eclipse 50.0% 0.01s 100.0% 127 128Out = [1, 3, 6, 8, 2, 4, 9, 7, 5] 129Yes (0.14s cpu) 130\end{verbatim}\end{quote} 131 132From the above result we can see how the profiler output contains four 133important areas of information: 134\begin{enumerate} 135\item The first line of output indicates whether the specified goal 136\textbf{succeeded}, \textbf{failed} or \textbf{aborted}. The 137\verb+profile/1+ predicate itself always succeeds. 138\item The line beginning \verb+Goal:+ shows the goal which was 139profiled. 140\item The next line shows the time spent executing the goal. 141\item Finally the predicates which were being executed when the 142profiler sampled, ranked in decreasing sample count order are shown. 143\end{enumerate} 144 145The problem with the results displayed above is that the sampling 146frequency is too low when compared to the total user time spent 147executing the goal. In fact in the above example the profiler was 148only able to take two samples before the goal terminated. 149 150The frequency at which the profiler samples is fixed, so in order to 151obtain more representative results one should have an auxiliary 152predicate which calls the goal a number of times, and compile and 153profile a call to this auxiliary predicate. eg. 154 155\begin{code} 156queen_100 :- 157 (for(_,1,100,1) do queen([1,2,3,4,5,6,7,8,9],_Out)). 158\end{code} 159 160Note that, when compiled, the above \verb+do/2+ loop would be 161efficiently implemented and not cause overhead that would distort the 162measurement. \See{See section \ref{sec:loops} for more information on 163logical loops} 164 165\begin{quote}\begin{verbatim} 166?- profile(queen_100). 167goal succeeded 168 169 PROFILING STATISTICS 170 -------------------- 171 172Goal: queen_100 173Total user time: 3.19s 174 175Predicate Module %Time Time %Cum 176-------------------------------------------------------- 177nodiag /3 eclipse 52.2% 1.67s 52.2% 178qdelete /4 eclipse 27.4% 0.87s 79.6% 179qperm /2 eclipse 17.0% 0.54s 96.5% 180safe /1 eclipse 2.8% 0.09s 99.4% 181queen /2 eclipse 0.6% 0.02s 100.0% 182 183Yes (3.33s cpu) 184\end{verbatim}\end{quote} 185 186In the above example, the profiler takes over three hundred samples 187resulting in a more accurate view of where the time is being spent in 188the program. In this instance we can see that more than half of the 189time is spent in the \verb+nodiag/3+ predicate, making it an ideal 190candidate for optimisation. This is left as an exercise for the 191reader. 192 193 194%---------------------------------------------------------------------- 195\section{Line coverage} 196%---------------------------------------------------------------------- 197\index{library!coverage} 198\index{coverage} 199\index{line coverage} 200The line coverage library provides a means to ascertain exactly how 201many times individual clauses are called during the evaluation of a 202query. 203 204\index{coverage counters} 205The library works by placing \emph{coverage counters} at strategic 206points throughout the code being analysed. These counters are 207incremented each time the evaluation of a query passes them. There 208are three locations in which coverage counters can be inserted. 209\quickrefstatic{Locations where coverage counters can be placed}{ 210\begin{enumerate} 211\item At the beginning of a code block. 212\item Between predicate calls within a code block. 213\item At the end of a code block. 214\end{enumerate} 215} 216A code block is defined to be a conjunction of predicate calls. ie. a 217sequence of goals separated by commas. 218 219As previously mentioned, by default, code coverage counters are 220inserted before and after every subgoal in the code. For instance, in 221the clause 222\begin{code} 223p :- q, r, s. 224\end{code} 225four counters would be inserted: before the call to \verb+q+, between 226\verb+q+ and \verb+r+, between \verb+r+ and \verb+s+, and after 227\verb+s+: 228\begin{quote}\begin{verbatim} 229p :- point(1), q, point(2), r, point(3), s, point(4). 230\end{verbatim}\end{quote} 231 232 233This is the most precise form provided. The counter values do not only 234show whether all code points were reached but also whether subgoals 235failed or aborted (in which case the counter before a subgoal will 236have a higher value than the counter after it). For example, the 237result of running the above code is: 238\begin{quote}\begin{alltt} 239p :- \HighGreen{43 } q, \HighGreen{25 } r, \HighGreen{25 } s \HighRed{0 } . 240\end{alltt}\end{quote} 241 242which indicates that \verb+q+ was called 43 times, but succeeded only 24325 times, \verb+r+ was called 25 times and succeeded always, and 244\verb+s+ was called 25 times and never succeeded. Coverage counts of 245zero are displayed in red (the final box) because they indicate 246unreached code. The format of the display is explained in the next 247section. 248 249%---------------------------------------------------------------------- 250\subsection{Compilation} 251%---------------------------------------------------------------------- 252\index{ccompile/1} 253\index{ccompile!coverage} 254In order to add the coverage counters to code, it must be compiled with 255the \bipref{ccompile/1}{../bips/lib/coverage/ccompile-1.html} 256predicate which can be found in the 257\bipref{coverage}{../bips/lib/coverage/index.html} library. 258 259The predicate \verb+ccompile/1+ (note the initial `c' stands for 260coverage) can be used in place of the normal \verb+compile/1+ 261predicate to compile a file with coverage counters. 262 263Here we see the results of compiling the \textbf{n-queens} example 264given in the previous section. 265\begin{quote}\begin{verbatim} 266?- coverage:ccompile(queens). 267coverage: inserted 22 coverage counters into module eclipse 268foo.ecl compiled traceable 5744 bytes in 0.00 seconds 269 270Yes (0.00s cpu) 271\end{verbatim}\end{quote} 272 273Once compiled, predicates can be called as usual and will (by default) 274have no visible side effects. Internally however, the counters will 275be incremented as the execution progresses. To see this in action, 276consider issuing the following query having compiled the previously 277defined code using \verb+ccompile/1+. 278\begin{quote}\begin{alltt} 279?- queens([1,2,3,4,5,6,7,8,9], Out). 280\end{alltt}\end{quote} 281 282The default behaviour of the \verb+ccompile/1+ predicate is to place 283coverage counters as explained above, however such a level of detail 284may be unnecessary. If one is interested in reachability analysis the 285two argument predicate \verb+ccompile/2+ \index{ccompile/2} 286\index{ccompile!coverage} can take a list of \verb+name:value+ pairs 287which can be used to control the exact manner in which coverage 288counters are inserted.\See{See 289\bipref{ccompile/2}{../bips/lib/coverage/ccompile-2.html} for a 290full list of the available flags.} In particular by specifying the 291option \verb+blocks_only:on+, counters will only be inserted at the 292beginning and end of code blocks. Reusing the above example this would 293result in counters at point(1) and point(4). 294 295\begin{quote}\begin{alltt} 296p :- \HighGreen{43 } q, r, s \HighRed{0 } . 297\end{alltt}\end{quote} 298 299This can be useful in tracking down unexpected failures by looking for 300exit counters which differ from entry counters, for example. 301 302 303%---------------------------------------------------------------------- 304\subsection{Results} 305%---------------------------------------------------------------------- 306 307\index{result/1} \index{result!coverage} To generate an html file 308containing the coverage counter results issue the following query. 309\begin{quote}\begin{verbatim} 310?- coverage:result(queens). 311\end{verbatim}\end{quote} 312This will create the result file \texttt{coverage/queens.html} which 313can be viewed using any browser. It contains a pretty-printed form of 314the source, annotated with the values of the code coverage counters as 315described above. An example is shown in figure \ref{fig:queens}. 316 317\begin{figure} 318\begin{center} 319\resizebox{0.5\textwidth}{!}{\includegraphics{coverage.eps}} 320\end{center} 321\caption{Results of running queens([1,2,3,4,5,6,7,8,9],_)} 322\label{fig:queens} 323\end{figure} 324 325\index{result/0} \index{result!coverage} For extra convenience the 326predicate \verb+result/0+ is provided which will create results for 327all files which have been compiled with coverage counters. 328 329\quickref{Result generating commands}{ 330\begin{description} 331\item[\bipref{result/0}{../bips/lib/coverage/result-0.html}] Creates 332results for all files which have been compiled with coverage counters. 333\item[\bipref{result/1}{../bips/lib/coverage/result-1.html}] This 334predicate takes a single argument which is the name of the file to 335print the coverage counters for. 336\item[\bipref{result/2}{../bips/lib/coverage/result-2.html}] 337\index{result/2} The result predicate has a two argument form, the 338second argument defining a number of flags which control (amongst 339other things) 340\begin{itemize} 341\item The directory in which to create the results file. Default: 342\texttt{coverage}. 343\item The format of the results file (html or text). Default: 344\texttt{html}. 345\end{itemize} 346\end{description} 347\See{See \bipref{coverage}{../bips/lib/coverage/index.html} library 348and \bipref{pretty_printer}{../bips/lib/pretty_printer/index.html} 349library for more details} 350} 351 352\index{reset_counters/0} \index{reset_counters!coverage} Having 353generated and viewed results for one run, the coverage counters can be 354reset by calling 355\begin{quote}\begin{verbatim} 356?- coverage:reset_counters. 357 358Yes (0.00s cpu) 359\end{verbatim}\end{quote} 360 361\index{program analysis|)} 362%HEVEA\cutend 363