编译、优化和调优
Table of Contents
1. eval-when
简而言之,就是指定 Lisp 代码在什么阶段执行。执行阶段由参数指定,分别是:
:compile-toplevel | 编译成 fasl 文件时执行 |
:load-toplevel | 会在编译时把 body 里代码作为 top-level 来编译,这样在加载 fasl 时才会生效。 |
:execute | 加载源代码文件时执行 |
比如调用 make-package,必须执行三个时态,才能正常用:
(eval-when (:compile-toplevel :load-toplevel :execute) (make-package :hello :use '(cl)))
如果没有指定 :execute,那么只能在编译文件、加载 fasl 文件时正常,而加载源代码文件时就要出错。如果不指定 :load-toplevel,在加载 fasl 文件后也一样找不到 :hello 这个包,因为 make-package 部分并没有编译——而只是在编译时执行了一下。
2. 编译成可执行文件
SBCL 中可以使用 sb-ext:save-lisp-and-die 函数,其中有几个参数:
:executable | 如果为 t,保存成 stand-alone 文件,这样包括 SBCL 的运行环境也打包进去了 |
:toplevel | 指定运行时的入口函数 |
例:
(save-lisp-and-die "xxx" :executable t :toplevel 'main)
3. 保存 image
SBCL
(save-lisp-and-die "文件名" :executable t :toplevel #'入口函数)
CCL 见:http://ccl.clozure.com/manual/chapter4.9.html#Saving-Applications
默认只是导出内存数据,如果要导出成二进制格式,记得 :prepend-kernel t 参数。
4. 查看内存占用情况
room 函数可以统计出内存使用情况,比如在 SBCL 中:
* (room) Dynamic space usage is: 53,022,160 bytes. Immobile space usage is: 14,938,976 bytes (54,256 bytes overhead). Read-only space usage is: 0 bytes. Static space usage is: 848 bytes. Control stack usage is: 1,992 bytes. Binding stack usage is: 656 bytes. Control and binding stack usage is for the current thread only. Garbage collection is currently enabled. Breakdown for dynamic space: 13,572,032 bytes for 93,091 simple-vector objects 12,773,808 bytes for 798,363 cons objects 10,627,840 bytes for 159,990 instance objects 2,687,840 bytes for 35,215 simple-array-unsigned-byte-8 objects 13,491,440 bytes for 253,346 other objects 53,152,960 bytes for 1,340,005 dynamic objects (space total) Breakdown for immobile space: 12,903,808 bytes for 20,327 code objects 1,234,656 bytes for 25,722 symbol objects 746,256 bytes for 20,371 other objects 14,884,720 bytes for 66,420 immobile objects (space total)