13

我有一个没有太多内存 (256Mb) 的 VPS,我正在尝试使用 SBCL+Hunchentoot 进行 Common Lisp 开发,以编写一些简单的网络应用程序。大量内存似乎在没有做任何特别复杂的事情的情况下被使用,并且在服务页面一段时间后它耗尽内存并且使用所有交换变得疯狂或者(如果没有交换)就死了。

所以我需要帮助:

  • 找出正在使用所有内存的内容(尤其是库或我)
  • 限制 SBCL 允许使用的内存量,以避免大量交换
  • 当内存用完时干净地处理事情,而不是崩溃(因为它是一个网络应用程序,我希望它继续运行并尝试清理)。

我认为前两个相当简单,但第三个甚至可能吗?人们如何在 Lisp 中处理内存不足或内存受限的情况?

(另外,我注意到 64 位 SBCL 使用的内存似乎是 32 位的两倍。这是预期的吗?如果可以节省大量内存,我可以运行 32 位版本)

4

4 回答 4

15

要限制 SBCL 的内存使用,请使用 --dynamic-space-size 选项(例如,sbcl --dynamic-space-size 128将内存使用限制为 128M)。

要找出谁在使用内存,您可以(room)在不同的时间调用(告诉正在使用多少内存的函数):在启动时,加载所有库之后,然后在工作期间(当然,(sb-ext:gc :full t)在房间之前调用而不是测量尚未收集的垃圾)。

此外,还可以使用 SBCL Profiler 来测量内存分配。

于 2009-04-02T09:53:16.110 回答
5

找出正在使用所有内存的内容(尤其是库或我)

Attila Lendvai 有一些特定于 SBCL 的代码来找出分配对象的来源。请参阅http://article.gmane.org/gmane.lisp.steel-bank.devel/12903并在需要时给他写一封私人邮件。

请务必尝试另一种实现,最好使用精确的 GC(如 Clozure CL),以确保它不是特定于实现的泄漏。

限制 SBCL 允许使用的内存量,以避免大量交换

已经被别人回答了。

当内存用完时干净地处理事情,而不是崩溃(因为它是一个网络应用程序,我希望它继续运行并尝试清理)。

256MB 很紧,但无论如何:安排一个重复的(可能是 1 秒)定时线程来检查剩余的可用空间。如果可用空间小于 X,则使用 exec() 将当前的 SBCL 进程映像替换为新的。

于 2009-04-03T15:31:57.137 回答
3

如果您没有任何类型声明,我希望 64 位 Lisp 占用的空间是 32 位的两倍。即使是普通的(小)int 也会使用 64 位的内存块。我不认为它会使用少于一个机器词,除非你声明它。

我对#2 和#3 无能为力,但如果你弄清楚#1,我怀疑这不会有问题。我已经看到 SBCL/Hunchentoot 实例运行了很长时间。如果我使用了大量的内存,那通常是我自己的错。:-)

于 2009-04-02T20:21:11.553 回答
1

我不会对使用两倍内存的 64 位 SBCL 感到惊讶,因为它可能会使用 64 位单元而不是 32 位单元,但是如果没有实际检查就不能肯定地说。

使内存停留时间超过预期的典型事情是不再有用的引用,它们仍然具有通往根分配集的路径(我发现哈希表是让这些事情逗留的好方法)。您可以尝试在代码中散布对 GC 的显式调用,并确保(尽可能)不将内容存储在全局变量中。

于 2009-04-02T09:47:17.217 回答