Clozure CL中文版020:剖析
Category:帮助手册剖析
使用Linux oprofile系统级分析器
oprofile 是一个系统级的分析器,可用于大多数现代Linux发行版。
这里没有真正记录oprofile及其配套程序的使用; 所描述的是一种生成符号信息的方法,该符号信息使得由opreport程序生成的概要分析摘要能够有意义地识别lisp函数。
生成用于oprofile的lisp映像
现代Linux使用’ELF’(可执行和链接格式)目标文件格式;如果该文件看起来是ELF目标文件并且它包含ELF符号信息,那么oprofile工具可以将符号名称与内存映射文件中的地址相关联。描述那些内存区域。所以,一般的想法是制作一个看起来像ELF共享库的lisp堆图像来欺骗 oprofile工具(我们实际上并没有通过ELF动态链接技术加载堆图像,但我们可以让它看起来像我们一样。)
先决条件
- oprofile 本身,如果尚未预先安装,几乎可以通过您的发行版的包管理系统获得。
- libelf,它提供了用于读取和编写ELF文件的实用程序(同样可能预先安装或可以轻松安装。)有些令人困惑的是,Linux上有两种libelf实现广泛使用,不同的发行版用不同的名称引用它们(它们可以作为’elfutils’软件包的一部分。)oprofile insterface旨在与libelf实现一起使用,其版本号目前约为147; 另一个(不兼容的)libelf实现的版本号大约为0.8。可能需要安装相应的开发包(-dev或-devel,usuallly)才能实际使用libelf共享库。
为Lisp函数生成ELF符号
为了创建可用于oprofile基于概要分析的lisp堆映像 ,我们需要:
- 加载我们想要分析的任何代码
- 生成一个文件,其中包含描述所有lisp函数的名称和地址的ELF符号信息。
这一步涉及到(来自Clozure CL内)
? (require “ELF”)
“ELF”
(“ELF”)
? (ccl::write-elf-symbols-to-file “home:elf-symbols”)
CCL :: WRITE-ELF-SYMBOLS-TO-FILE的参数可以是任何可写路径名。该函数将执行将lisp函数固定在内存中所需的任何操作(以便它们不会被GC移动),然后将ELF目标文件写入指定的路径名。这通常需要几秒钟。
- 生成一个lisp堆映像,其中前一步骤中生成的ELF符号被预先添加。
函数CCL:SAVE-APPLICATION提供了一个:PREPEND-KERNEL参数,它通常用于保存内核和堆映像占用单个文件的独立应用程序。:PREPEND-KERNEL并不关心图像前面的内容,我们可以很容易地要求它预先添加上一步生成的ELF符号文件。
? (save-application “somewhere/image-for-profiling” :prepend-kernel “home:elf-symbols”)
如果你然后运行
shell> ccl64 somewhare/image-for-profiling
由该图像中的oprofile采样的任何lisp代码将被“符号”地标识opreport。
例
;;; Define some lisp functions that we want to profile and save
;;; a profiling-enabled image. In this case, we just want to
;;; define the FACTORIAL funcion, to keep things simple.
? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
FACT
? (require “ELF”)
“ELF”
(“ELF”)
? (ccl::write-elf-symbols-to-file “home:elf-symbols”)
“home:elf-symbols”
? (save-application “home:profiled-ccl” :prepend-kernel “home:elf-symbols”)
;;; Setup oprofile with (mostly) default arguments. This example was
;;; run on a Fedora 8 system where an uncompressed ‘vmlinux’ kernel
;;; image isn’t readily available.
;;; Note that use of ‘opcontrol’ generally requires root access, e.g.,
;;; ‘sudo’ or equivalent:
[~] gb@rinpoche> sudo opcontrol –no-vmlinux –setup
;;; Start the profiler
[~] gb@rinpoche> sudo opcontrol –start
Using 2.6+ OProfile kernel interface.
Using log file /var/lib/oprofile/samples/oprofiled.log
Daemon started.
Profiler running.
;;; Start CCL with the “profiled-ccl” image created above.
;;; Invoke “(FACT 10000)”
[~] gb@rinpoche> ccl64 profiled-ccl
Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk (LinuxX8664)!
? (null (fact 10000))
NIL
? (quit)
;;; We could stop the profiler (opcontrol –stop) here; instead,
;;; we simply flush profiling data to disk, where ‘opreport’ can
;;; find it.
[~] gb@rinpoche> sudo opcontrol –dump
;;; Ask opreport to show us where we were spending time in the
;;; ‘profiled-ccl’ image.
[~] gb@rinpoche> opreport -l profiled-ccl | head
CPU: Core 2, speed 1596 MHz (estimated)
Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
samples % symbol name
6417 65.2466 <Compiled-function.(:INTERNAL.MULTIPLY-UNSIGNED-BIGNUM-AND-1-DIGIT-FIXNUM.MULTIPLY-BIGNUM-AND-FIXNUM).(Non-Global)..0x30004002453F>
3211 32.6487 <Compiled-function.%MULTIPLY-AND-ADD4.0x300040000AAF>
17 0.1729 <Compiled-function.%%ONE-ARG-DCODE.0x3000401740AF>
11 0.1118 <Compiled-function.%UNLOCK-RECURSIVE-LOCK-OBJECT.0x30004007F7DF>
10 0.1017 <Compiled-function.AUTO-FLUSH-INTERACTIVE-STREAMS.0x3000404ED6AF>
7 0.0712 <Compiled-function.%NANOSLEEP.0x30004040385F>
7 0.0712 <Compiled-function.%ZERO-TRAILING-SIGN-DIGITS.0x300040030F3F>
问题
CCL :: WRITE-ELF-SYMBOLS-TO-FILE目前仅适用于x86-64; 它当然可以用于ppc32 / ppc64。
到目前为止,还没有人能够生成oprofile / opreport选项,它们应该生成调用堆栈信息,生成有意义的调用堆栈信息。
截至几个月前,曾尝试“动态”提供oprofile / opreport的符号信息,例如,用于JIT编译或其他增量编译方案。这显然更接近The Right Thing,但在实验代码广泛使用之前可能需要一段时间。
使用Apple的CHUD计量工具
Apple的CHUD包提供了库,内核扩展以及一组图形和命令行程序,可用于测量应用程序和系统性能的许多方面。
其中一个程序是Shark应用程序(通常安装在“/ Developer / Applications / Performance Tools / Shark.app”中),它提供了一个图形用户界面,用于探索和分析性能分析结果,并提供用于创建“采样配置”的工具(请参阅以下),除其他外。这里没有真正记录Shark的使用(可以在“Developer / Documentation / CHUD / Shark / SharkUserGuide.pdf”中找到Shark手册); 所描述的是一种提供有关Lisp函数名称和地址的信息的方法,以便Shark可以在其输出中有意义地识别这些函数。
先决条件
Apple的CHUD工具已经与最新的几个XCode版本一起发布。确定是否安装工具的一种方法是运行:
$ /usr/bin/shark -v
在终端或Emacs shell缓冲区中。如果返回输出就像
shark 4.7.3 (365)
然后安装CHUD包。输出就像
shark: Command not found.
强烈暗示它不是……
生成用于Shark的lisp图像
Shark只能正确识别在目标应用程序加载的共享库中定义的函数。(任何其他函数将由描述为“未知库”的十六进制地址标识;十六进制地址通常稍微接近实际函数,但它是启发式确定的并且并不总是准确的。)
出于这些原因,需要在一个lisp会话中加载您希望分析的代码,保存本机(Mach-O库)映像,并在使用该本机映像的新会话中调用Shark。(加载CHUD-METERING模块也很有用,它定义了CHUD:METER和朋友。
用法简介
[src/ccl-dev] gb@antinomial> ccl64Welcome to Clozure Common Lisp Version 1.7-dev-r14624M-trunk (DarwinX8664)!? (defun fact(n) (if (zerop n) 1 (* n (fact (1- n)))))FACT? (require “CHUD-METERING”)”CHUD-METERING”(“CHUD-METERING”)? (save-application “ccl:dx86cl64.dylib” :native t)[src/ccl-dev] gb@antinomial> ccl64 -I dx86cl64.dylibWelcome to Clozure Common Lisp Version 1.7-dev-r14624M-trunk (DarwinX8664)!? (chud:meter (dotimes (i 1000) (fact 1000)));;; Waiting for shark to process samples …done.NIL
并且,在返回结果几秒后,将在Shark.app中打开名称格式为“session_nnn.mshark”的文件。
第一次将CHUD:METER用于lisp会话时,它会做一些事情来准备后续的分析会话。那些东西包括:
- 创建一个目录来存储与在此lisp会话中使用CHUD工具相关的文件。此目录在用户的主目录中创建,并具有以下格式的名称:
profiling-session-<lisp-kernel>-<pid>_<mm>-<dd>-<yyyy>_<h>.<m>.<s>
- 运行鲨鱼程序(“/ usr / bin / shark”)并等待它准备好接收控制其操作的信号。
这种启动活动通常需要几秒钟; 在完成之后,随后使用CHUD:METER不涉及这种开销。(参见下面的讨论:RESET。)
任何启动活动完成后,CHUD:METER安排向正在运行的鲨鱼程序发送“开始分析”信号,执行表单,向鲨鱼程序发送“停止分析”信号,并读取其诊断输出,查找它生成的“.mshark”文件的名称。如果它能够找到这个文件名,它会安排“Shark.app”打开它。
分析“配置”
默认情况下,鲨鱼分析会话将:
- 使用“基于时间”的采样,定期中断lisp进程并记录程序计数器的值和至少几个级别的调用历史记录。
- 每毫秒进行一次采样
- 运行最多30秒,除非被告知要提前停止。
这被称为“默认配置”; 可以使用Shark应用程序中“配置”菜单上的项目来创建备用配置,这些配置提供不同类型的配置文件参数,并将这些配置保存在文件中以供后续重用。(CHUD知道如何监控的一组内容非常有趣。)
您使用备用配置文件配置(通过Shark.app创建和“导出”)与CHUD:METER,但界面有点尴尬。
参考
chud:*shark-config-file*[变量]
当非null时,这应该是Shark.app中“配置编辑器”创建的备用性能分析配置文件的路径名。
chud:meter form &key (reset nil)(debug-output nil)[Macro]
执行FORM(任意lisp表单)并返回它返回的任何结果,并在表单执行期间启用CHUD分析。尝试确定shark程序写入分析数据的会话文件(* .mshark)的名称,并在Shark应用程序中打开此文件。
参数:
调试输出
当非零时,导致鲨鱼程序生成的输出回显到* TERMINAL-IO *。用于调试。
重启
当非nil时,终止由此lisp会话中先前调用CHUD:METER创建的任何正在运行的shark程序实例,生成一个新的.spatch文件(描述lisp函数的名称和地址),并启动一个新的实例鲨鱼计划; 如果CHUD:* SHARK-CONFIG-FILE *在启动此新实例时为非NIL,则会告知该实例使用指定的配置文件进行性能分析(代替默认的性能分析配置)。
承认
Dan Knapp和Hamilton Link都在过去向openmcl-devel发布了类似的CHUD接口; 汉密尔顿还报告了CHUD开发人员的spatch机制中的错误(并修复了这些错误。)
http://mip.i3geek.com