为什么Common Lisp(SBCL)会为一个简单的程序使用如此多的内存?

时间:2012-01-25 11:19:13

标签: common-lisp sbcl

因为我是Common Lisp的新手,所以我尝试使用Common Lisp(SPOJ)解决SBCL上的问题。 The first problem是一个简单的任务,在找到数字42之前读取数字。这是我的解决方案:

(defun study-num ()
  (let ((num (parse-integer (read-line t))))
    (when (not (= num 42))
      (format t "~A~%" num)
      (study-num))))
(study-num)

接受解决方案。但当我查看结果的细节时,我发现它使用了57M的MEM!这是不合理的,但我无法弄清楚为什么。我该怎么做才能进行优化?

3 个答案:

答案 0 :(得分:4)

您正在进行重复的递归调用,没有启用足够的优化以启用尾部调用消除(SBCL会执行此操作,但仅当您将“优化速度”设置为高并且“优化调试信息”设置为低时)。

Common Lisp标准将尾部调用消除作为实现质量问题,并提供其他循环结构(如LOOP或DO,两者都可能适用于此应用程序)。

此外,由于需要引入其运行时环境和基本映像,新启动的SBCL可能会比您预期的要大。

答案 1 :(得分:4)

我认为你没有意识到Common Lisp是一个在线语言环境,其中包含完整的库和编译器,只是为了给你提供第一个提示。在那之后,你的程序加载可能是一个几乎没有明显的大小增加。 Lisp不会编译和链接由您的代码组成的独立可执行文件以及从您的代码可以访问的任何lib例程。这就是C和类似语言的作用。相反,Lisp将您的代码添加到其已经相当大的在线环境中。作为一个新用户,它接缝可怕。但是如果你有一台具有100 MB内存的现代通用计算机,那么当你享受在线环境的好处时,它很快就会成为你忘记的东西。 Thins也被称为“动态语言环境”。

答案 2 :(得分:4)

各种Lisp实现有不同的方法来创建程序。一种是转储Lisp系统内存的映像并将其写入磁盘。重新启动时,此图像将加载运行时,然后再次启动。这很常见。

这也是SBCL保存可执行文件时的作用。因此,这个可执行文件包括完整的SBCL。

其他一些实现使用图像创建较小的可执行文件(CLISP),有些可以从可执行文件中删除未使用的代码(Allegro CL,LispWorks),而其他实现则通过编译到C(mocl)创建非常小的程序。

SBCL只有一种简单的方法来减小可执行文件的大小:可以压缩图像。