我有一个内存不是太多(256Mb)的 VPS,我尝试使用它通过 SBCL+Hunchentoot 进行 Common Lisp 开发,以编写一些简单的 Web 应用程序。大量的内存似乎在没有做任何特别复杂的事情的情况下被使用,并且在提供页面一段时间后,它耗尽了内存,要么疯狂地使用所有交换,要么(如果没有交换)就死掉了。

所以我需要帮助:

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

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

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

有帮助吗?

解决方案

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

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

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

其他提示

找出使用所有内存的方法(如果是库或我,尤其是我)

Attila Lendvai 有一些特定于 SBCL 的代码来查找分配的对象来自何处。参考 http://article.gmane.org/gmane.lisp.steel-bank.devel/12903 如果需要的话,给他写一封私人邮件。

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

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

其他人已经回答了。

当内存耗尽而不是崩溃时,请干净地处理内容(因为这是一个网络应用程序,我希望它继续下去并尝试清理)。

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

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

我无法帮助解决#2 和#3,但如果您弄清楚#1,我怀疑这不会是问题。我已经看到 SBCL/Hunchentoot 实例运行了很长时间。如果我使用了过多的内存,通常是我自己的错。:-)

我不会对使用两倍内存的 64 位 SBCL 感到惊讶,因为它可能会使用 64 位单元而不是 32 位单元,但在没有实际检查的情况下无法确定。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top