source: trunk/source/doc/src/profile.xml @ 9569

Last change on this file since 9569 was 9569, checked in by gz, 12 years ago

Add Profiling section, with oprofile and CHUD docs. Move q-and-a to the end.

File size: 16.2 KB
Line 
1<?xml version="1.0" encoding="utf-8"?>
2<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
3<!ENTITY rest "<varname>&amp;rest</varname>">
4<!ENTITY key "<varname>&amp;key</varname>">
5<!ENTITY optional "<varname>&amp;optional</varname>">
6<!ENTITY body "<varname>&amp;body</varname>">
7<!ENTITY aux "<varname>&amp;aux</varname>">
8<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
9<!ENTITY CCL "Clozure CL">
10]>
11
12  <chapter id="Profiling">
13    <title>Profiling</title>
14
15    <sect1 id="Profiling-Using the Linux oprofile system-level profiler">
16      <title>Using the Linux oprofile system-level profiler</title>
17
18      <para><ulink url="http://oprofile.sourceforge.net"><code>oprofile</code></ulink> is
19      a system-level profiler that's available for most modern Linux distributions.</para>
20
21      <para>Use of oprofile and its companion programs isn't really documented here; what
22      is described is a way of generating symbolic information that enables profiling
23      summaries generated by the <code>opreport</code> program to identify lisp functions
24      meaningfully.</para>
25
26      <sect2 id="Profiling-oprofile-generating-a-lisp-image-for-use-with-oprofile">
27        <title>Generating a lisp image for use with oprofile</title>
28
29        <para>Modern Linux uses the 'ELF" (Executable and Linking Format) object file
30        format; the oprofile tools can associate symbolic names with addresses in a
31        memory-mapped file if that file appears to be an ELF object file and if it
32        contains ELF symbol information that describes those memory regions.  So, the
33        general idea is to make a lisp heap image that looks enough like an ELF shared
34        library to fool the <code>oprofile</code> tools (we don't actually load heap
35        images via ELF dynamic linking technology, but we can make it look like we
36        did.)</para>
37
38      </sect2>
39      <sect2 id="Profiling-oprofile-prerequisites">
40        <title>Prerequisites</title>
41
42        <itemizedlist>
43          <listitem>
44            <para><code>oprofile</code> itself, which is almost certainly available via
45            your distribution's package management system if not already
46            preinstalled.</para>
47          </listitem>
48          <listitem>
49            <para><code>libelf</code>, which provides utilities for reading and writing
50            ELF files (and is likewise likely preinstalled or readily installable.)</para>
51          </listitem>
52        </itemizedlist>
53      </sect2>
54      <sect2 id="Profiling-oprofile-generating-elf-symbols-for-lisp-functions">
55        <title>Generating ELF symbols for Lisp functions</title>
56
57        <para>In order to create a lisp heap image which can be used for
58        <code>oprofile</code>- based profiling, we need to:</para>
59        <orderedlist>
60          <listitem>
61            <para>load any code that we want to profile</para>
62          </listitem>
63          <listitem>
64            <para>generate a file that contains ELF symbol information describing the
65            names and addresses of all lisp functions.</para>
66            <para>This step involves doing (from within &CCL;)</para>
67            <programlisting>
68? (require "ELF")
69"ELF"
70("ELF")
71
72? (ccl::write-elf-symbols-to-file "home:elf-symbols")
73            </programlisting>
74            <para>The argument to CCL::WRITE-ELF-SYMBOLS-TO-FILE can be any writable
75            pathname.  The function will do whatever's necessary to nail lisp functions
76            down in memory (so that they aren't moved by GC), then write an ELF object
77            file to the indicated pathname.  This typically takes a few seconds.</para>
78          </listitem>
79          <listitem>
80            <para>Generate a lisp heap image in which the ELF symbols generated in the
81            previous step are prepended.</para>
82            <para>The function CCL:SAVE-APPLICATION provides a :PREPEND-KERNEL argument,
83            which is ordinarily used to save a standalone application in which the kernel
84            and heap image occupy a single file.  :PREPEND-KERNEL doesn't really care what
85            it's prepending to the image, and we can just as easily ask it to prepend the
86            ELF symbol file generated in the previous step.</para>
87            <programlisting>
88? (save-application "somewhere/image-for-profiling"
89    :prepend-kernel "home:elf-symbols")
90            </programlisting>
91            <para>If you then run</para>
92            <programlisting>
93shell> ccl64 somewhare/image-for-profiling
94            </programlisting>
95            <para>any lisp code sampled by oprofile in that image will be identified
96            "symbolically" by <code>opreport</code>.</para>
97          </listitem>
98        </orderedlist>
99      </sect2>
100      <sect2 id="Profiling-oprofile-example">
101        <title>Example</title>
102        <programlisting>
103;;; Define some lisp functions that we want to profile and save
104;;; a profiling-enabled image.  In this case, we just want to
105;;; define the FACTORIAL funcion, to keep things simple.
106? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
107FACT
108? (require "ELF")
109"ELF"
110("ELF")
111? (ccl::write-elf-symbols-to-file "home:elf-symbols")
112"home:elf-symbols"
113? (save-application "home:profiled-ccl" :prepend-kernel "home:elf-symbols")
114
115;;; Setup oprofile with (mostly) default arguments.  This example was
116;;; run on a Fedora 8 system where an uncompressed 'vmlinux' kernel
117;;; image isn't readily available.
118
119;;; Note that use of 'opcontrol' generally requires root access, e.g.,
120;;; 'sudo' or equivalent:
121
122[~] gb@rinpoche> sudo opcontrol --no-vmlinux --setup
123
124;;; Start the profiler
125
126[~] gb@rinpoche> sudo opcontrol --start
127Using 2.6+ OProfile kernel interface.
128Using log file /var/lib/oprofile/samples/oprofiled.log
129Daemon started.
130Profiler running.
131
132;;; Start CCL with the "profiled-ccl" image created above.
133;;; Invoke "(FACT 10000)"
134
135[~] gb@rinpoche> ccl64 profiled-ccl
136Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk  (LinuxX8664)!
137? (null (fact 10000))
138NIL
139? (quit)
140
141;;; We could stop the profiler (opcontrol --stop) here; instead,
142;;; we simply flush profiling data to disk, where 'opreport' can
143;;; find it.
144
145[~] gb@rinpoche> sudo opcontrol --dump
146
147;;; Ask opreport to show us where we were spending time in the
148;;; 'profiled-ccl' image.
149
150[~] gb@rinpoche> opreport -l profiled-ccl | head
151CPU: Core 2, speed 1596 MHz (estimated)
152Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
153samples  %        symbol name
1546417     65.2466  &lt;Compiled-function.(:INTERNAL.MULTIPLY-UNSIGNED-BIGNUM-AND-1-DIGIT-FIXNUM.MULTIPLY-BIGNUM-AND-FIXNUM).(Non-Global)..0x30004002453F&gt;
1553211     32.6487  &lt;Compiled-function.%MULTIPLY-AND-ADD4.0x300040000AAF&gt;
15617        0.1729  &lt;Compiled-function.%%ONE-ARG-DCODE.0x3000401740AF&gt;
15711        0.1118  &lt;Compiled-function.%UNLOCK-RECURSIVE-LOCK-OBJECT.0x30004007F7DF&gt;
15810        0.1017  &lt;Compiled-function.AUTO-FLUSH-INTERACTIVE-STREAMS.0x3000404ED6AF&gt;
1597         0.0712  &lt;Compiled-function.%NANOSLEEP.0x30004040385F&gt;
1607         0.0712  &lt;Compiled-function.%ZERO-TRAILING-SIGN-DIGITS.0x300040030F3F&gt;
161        </programlisting>
162      </sect2>
163      <sect2 id="Profiling-oprofile-Issues">
164        <title>Issues</title>
165        <para>CCL::WRITE-ELF-SYMBOLS-TO-FILE currently only works on x86-64; it certainly
166        -could- be made to work on ppc32/ppc64 as well.</para>
167
168        <para>So far, no one has been able to make oprofile/opreport options that're
169        supposed to generate call-stack info generate meaningful call-stack info.</para>
170
171        <para>As of a few months ago, there was an attempt to provide symbol info for
172        oprofile/opreport "on the fly", e.g., for use in JIT compilation or other
173        incremental compilations scenarios.  That's obviously more nearly The Right Thing,
174        but it might be awhile before that experimental code makes it into widespread
175        use.</para>
176      </sect2>
177    </sect1>
178
179    <sect1 id="Profiling-Using-Apples-CHUD-metering-tools">
180      <title>Using Apple's CHUD metering tools</title>
181     
182      <sect2 id="Profiling-CHUD-prerequisites">
183        <title>Prerequisites</title>
184
185        <para>Apple's CHUD metering tools are available (as of this writing) from:</para>
186
187        <para><ulink url="ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/">
188          ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/</ulink>.</para>
189
190        <para>The CHUD tools are also generally bundled with Apple's XCode tools.  CBUD
191        4.5.0 (which seems to be bundled with XCode 3.0) seems to work well with this
192        interface; later versions may have problems.  Versions of CHUD as old as 4.1.1 may
193        work with 32-bit PPC versions of CCL; later versions (not sure exactly -what-
194        versions) added x86, ppc64, and x86-64 support.</para>
195
196        <para>One way to tell whether any version of the CHUD tools is installed is to try
197        to invoke the "shark" command-line program (/usr/bin/shark) from the shell:</para>
198        <programlisting>
199shell> shark --help
200        </programlisting>
201        <para>and verifying that that prints a usage summary.</para>
202
203        <para>CHUD consists of several components, including command-line programs, GUI
204        applications, kernel extensions, and "frameworks" (collections of libraries,
205        headers, and other resources which applications can use to access functionality
206        provided by the other components.)  Past versions of &CCL;/OpenMCL have used the
207        CHUD framework libraries to control the CHUD profiler.  Even though the rest of
208        CHUD is currently 64-bit aware, the frameworks are unfortunately still only
209        available as 32-bit libraries, so the traditional way of controlling the profiling
210        facility from &CCL; has only worked from DarwinPPC32 versions.</para>
211
212        <para>Two of the CHUD component programs are of particular interest:</para>
213
214        <orderedlist>
215          <listitem>
216            <para>The "Shark" application (often installed in
217            "/Developer/Applications/Performance Tools/Shark.app"), which provides a
218            graphical user interface for exploring and analyzing profiling results and
219            provides tools for creating "sampling configurations" (see below), among other
220            things.</para>
221          </listitem>
222          <listitem>
223            <para>The "shark" program ("/usr/bin/shark"), which can be used to control the
224            CHUD profiling facility and to collect sampling data, which can then be
225            displayed and analyzed in Shark.app.</para>
226          </listitem>
227        </orderedlist>
228
229        <para>The fact that these two (substantially different) programs have names that
230        differ only in alphabetic case may be confusing.  The discussion below tries to
231        consistently distinguish between "the shark program" and "the Shark
232        application".</para>
233
234      </sect2>
235      <sect2 id="Profiling-CHUD-usage-synopsis">
236          <title>Usage synopsis</title>
237          <programlisting>
238? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
239FACT
240? (require "CHUD-METERING")
241"CHUD-METERING"
242("CHUD-METERING")
243? (chud:meter (null (fact 10000)))
244NIL           ; since that large number is not NULL
245          </programlisting>
246
247          <para>and, a few seconds after the result is returned, a file whose name is of
248          the form "session_nnn.mshark" will open in Shark.app.</para>
249
250          <para>The fist time that CHUD:METER is used in a lisp session, it'll do a few
251          things to prepare subsequent profiling sessions.  Those things include:</para>
252
253          <itemizedlist>
254            <listitem>
255              <para>creating a directory to store files that are related to using the CHUD
256              tools in this lisp session.  This directory is created in the user's home
257              directory and has a name of the form:</para>
258
259              <programlisting>
260profiling-session-&lt;lisp-kernel&gt;-&lt;pid&gt;_&lt;mm&gt;-&lt;dd&gt;-&lt;yyyy&gt;_&lt;h&gt;.&lt;m&gt;.&lt;s&gt;
261              </programlisting>
262
263              <para>where &lt;pid&gt; is the lisp's process id, &lt;lisp-kernel&gt; is the
264              name of the lisp kernel (of all things ...), and the other values provide a
265              timestamp.</para>
266            </listitem>
267            <listitem>
268              <para>does whatever needs to be done to ensure that currently-defined lisp
269              functions don't move around as the result of GC activity, then writes a text
270              file describing the names and addresses of those functions to the
271              profiling-session directory created above.  (The naming conventions for and
272              format of that file are described in</para>
273              <para>
274              <ulink url="http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42">http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42</ulink></para>
275            </listitem>
276            <listitem>
277              <para>run the shark program ("/usr/bin/shark") and wait until it's ready to
278              receive signals that control its operation.</para>
279            </listitem>
280          </itemizedlist>
281
282          <para>This startup activity typically takes a few seconds; after it's been
283          completed, subsequent use of CHUD:METER doesn't involve that overhead.  (See the
284          discussion of :RESET below.)</para>
285
286          <para>After any startup activity is complete, CHUD:METER arranges to send a
287          "start profiling" signal to the running shark program, executes the form, sends
288          a "stop profiling" signal to the shark program, and reads its diagnostic output,
289          looking for the name of the ".mshark" file it produces.  If it's able to find
290          this filename, it arranges for "Shark.app" to open it.</para>
291        </sect2>
292
293        <sect2 id="Profiling-CHUD-profiling-configurations">
294          <title>Profiling "configurations"</title>
295
296          <para>By default, a shark profiling session will:</para>
297          <itemizedlist>
298            <listitem>
299              <para>use "time based" sampling, to periodically interrupt the lisp
300            process and note the value of the program counter and at least a few levels of
301            call history.</para>
302            </listitem>
303            <listitem>
304              <para>do this sampling once every millisecond</para>
305            </listitem>
306            <listitem>
307              <para>run for up to 30 seconds, unless told to stop earlier.</para>
308            </listitem>
309          </itemizedlist>
310
311          <para>This is known as "the default configuration"; it's possible to use items
312          on the "Config" menu in the Shark application to create alternate configurations
313          which provide different kinds of profiling parameters and to save these
314          configurations in files for subsequent reuse.  (The set of things that CHUD
315          knows how to monitor is large and interesting.)</para>
316
317          <para>You use alternate profiling configurations (created and "exported" via
318          Shark.app) with CHUD:METER, but the interface is a little awkward.</para>
319        </sect2>
320
321        <sect2 id="Profiling-CHUD-Reference">
322          <title>Reference</title>
323
324          <para>
325            <indexterm zone="chud_shark-config-file"/>
326            <command><varname id="chud_shark-config-file">CHUD:*SHARK-CONFIG-FILE*</varname> [Variable]</command>
327          </para>
328
329          <para>When non-null, this should be the pathname of an alternate profiling
330          configuration file created by the "Config Editor" in Shark.app.</para>
331
332          <para>
333            <indexterm zone="chud_meter"/>
334            <command><varname id="chud_meter">CHUD:METER</varname> form &key; (reset nil) (debug-output nil) [Macro]</command>
335          </para>
336             
337          <para>Executes FORM (an arbitrary lisp form) and returns whatever result(s) it
338          returns, with CHUD profiling enabled during the form's execution.  Tries to
339          determine the name of the session file (*.mshark) to which the shark program
340          wrote profiling data and opens this file in the Shark application.</para>
341         
342          <para>Arguments:</para>
343
344          <variablelist>
345            <varlistentry>
346              <term><varname>debug-output</varname></term>
347              <listitem>
348                <para>when non-nil, causes output generated by the shark program to be
349                echoed to *TERMINAL-IO*.  For debugging.</para>
350              </listitem>
351            </varlistentry>
352            <varlistentry>
353              <term><varname>reset</varname></term>
354              <listitem>
355                <para>when non-nil, terminates any running instance of the shark program
356                created by previous invocations of CHUD:METER in this lisp session,
357                generates a new .spatch file (describing the names and addresses of lisp
358                functions), and starts a new instance of the shark program; if
359                CHUD:*SHARK-CONFIG-FILE* is non-NIL when this new instance is started,
360                that instance is told to use the specified config file for profiling (in
361                lieu of the default profiling configuration.)</para>
362              </listitem>
363            </varlistentry>
364          </variablelist>
365        </sect2>
366
367        <sect2 id="Profiling-CHUD-Acknowledgments">
368          <title>Acknowledgement</title>
369          <para>Both Dan Knapp and Hamilton Link have posted similar CHUD interfaces to
370          openmcl-devel in the past; Hamilton's also reported bugs in the spatch mechanism
371          to CHUD developers (and gotten those bugs fixed.)</para>
372        </sect2>
373
374      </sect1>
375
376  </chapter>
Note: See TracBrowser for help on using the repository browser.