Web服务 – 在一个长期运行的Common Lisp应用程序中,应该采用什么策略来管理垃圾?

如果我在Common Lisp映像中托管长时间运行的应用程序,例如Web服务器,应该使用什么策略来管理垃圾回收器?

我假设,默认情况下,垃圾收集器有权花费很长时间整理堆,有时候我无法预测.这可能会以不希望的方式影响特定的浏览器请求.

Common Lisp有没有方法来控制?也许鼓励它以“小而常”的方式工作?

几个Lisp实现有优秀的垃圾收集器.一个特殊的问题是Lisp应用程序通常具有较高的小对象分配率(conses,…).

有几件事要考虑.

精确与保守GC.我不是Lisp的保守GC(Boehm等)的巨大粉丝.保守的GC的问题是它们没有找到所有的垃圾.这可能是长时间运行的程序的问题,导致碎片化,而不能回收未使用的内存.精确的GC正在使用Lisp数据的标签信息,并且可以识别每个对象的每个数据类型.保守的GC是针对不使用标记数据(C,…)的编程语言实现而发明的.
>复制GC,压缩GC.为了处理长时间运行的Lisps中的内存碎片,一个压缩和本地化对象的GC可能是有用的.当哈希表需要重新刷新(因为位置更改)时,有时会出现问题.复制GC可能需要更多的内存(因为存在内存和从空间).但是当GC将对象从一个存储空间复制到另一个存储空间时,它会自动使其更紧凑.更高级的GC(像在Lisp机器上)也可以对对象进行排序,并将彼此相似的对象分配到彼此附近 – 假设这将加速访问对象.
>短暂GC.这意味着有一个第一个GC阶段,专门在主存储器中运行,并从内存管理单元得到一些支持,以识别已更改的内存区域.扫描主存储器比扫描虚拟内存快,只扫描改变的内存区域进一步减少了工作量.当很多对象被分配并且迅速变成垃圾时,这给了很短的GC暂停.
代际GC.通常GC现在是世代.有一代以上的生物将能够存活下来的几种GC被提升为老一代.通常只有第一代是经常GCed的.
>调整.例如,LispWorks和Allegro CL的GC有很多调谐旋钮.特别是对于长时间运行的应用程序,阅读手册是有意义的,例如调整代数,尺寸和其他内容.
>虚拟内存.通过虚拟内存的GC通常很慢.如果可能的话避免这种情况 – 给机器添加更多的RAM.
>手动内存管理.例如,CL-HTTP Web服务器使用资源进行一些手动内存管理.这些是可以非常快速重新初始化的预分配对象池. Lisp机器正在使用这么多.它们的典型用途是在流的读缓冲区中.通过每次读取操作来创建新字符串,而不是使用可重用缓冲区是有用的.
>堆栈分配.一些Common Lisp允许堆栈分配一些数据 – 让块自动释放内存.这就假设在离开块时不再引用内存.
>并发GC. Common Lisp实现中没有一个对并发Lisp线程具有并发GC AND支持.一些实现具有并发Lisp线程,但GC将在工作时停止它们.
>剖析GC.如果您不确定分配发生的位置以及GC执行的操作,则需要使用分析信息查找.

如果您的Lisp具有在主内存中运行的精确代数GC,则很难在长暂停时出现问题. Clozure CL(一个免费的Common Lisp实现)例如具有非常好的GC实现.你想避免虚拟内存中的内存碎片和垃圾收集.如果需要,使用64位Lisp实现更多的主内存.

指针:

> Clozure CL,Understanding and Configuring the Garbage Collector
> CMUCL,Garbage Collection
> LispWorks,Storage Management
> Allegro CL,Garbage Collection

从文档可以看出,LispWorks和Allegro CL有很多旋钮用于调整GC.

Common Lisp具有处理实现环境的几个功能. (ROOM)是一个概述内存使用情况的功能. (ROOM t)给出了更多的细节(这里是LispWorks):

CL-USER 2 > (room t)
 Generation 0:  Total Size 1823K, Allocated 1090K, Free 725K 
          Segment 2008AAB8: Total Size 507K, Allocated 361K, Free 142K
                    minimum free space 64K, 
                      Awaiting promotion = 0K, sweeps before promotion =10
          Segment 217E7050: Total Size 1315K, Allocated 729K, Free 582K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =2
 Generation 1:  Total Size 1397K, Allocated 513K, Free 871K 
          Segment 20CB9A50: Total Size 68K, Allocated 48K, Free 15K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
          Segment 216D7050: Total Size 1088K, Allocated 331K, Free 752K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
          Segment 2004E4F8: Total Size 241K, Allocated 133K, Free 103K
                    minimum free space 0K, static
 Generation 2:  Total Size 2884K, Allocated 1290K, Free 1585K 
          Segment 21417050: Total Size 2816K, Allocated 1227K, Free 1584K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
          Segment 20DA5DA0: Total Size 68K, Allocated 62K, Free 1K
                    minimum free space 117K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
 Generation 3:  Total Size 19373K, Allocated 19232K, Free 128K 
          Segment 20109A50: Total Size 11968K, Allocated 11963K, Free 0K
                    minimum free space 3K, 
                      Awaiting promotion = 0K, sweeps before promotion =10
          Segment 20DB6E18: Total Size 6528K, Allocated 6396K, Free 128K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =10
          Segment 20CCAAC8: Total Size 876K, Allocated 872K, Free 0K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =10

Total Size 25792K, Allocated 22127K, Free 3310K
相关文章
相关标签/搜索