我假设,默认情况下,垃圾收集器有权花费很长时间整理堆,有时候我无法预测.这可能会以不希望的方式影响特定的浏览器请求.
Common Lisp有没有方法来控制?也许鼓励它以“小而常”的方式工作?
解决方法
有几件事要考虑.
精确与保守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,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,sweeps before promotion =4 Segment 216D7050: Total Size 1088K,Allocated 331K,Free 752K minimum free space 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,sweeps before promotion =4 Segment 20DA5DA0: Total Size 68K,Allocated 62K,Free 1K minimum free space 117K,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,sweeps before promotion =10 Segment 20DB6E18: Total Size 6528K,Allocated 6396K,Free 128K minimum free space 0K,sweeps before promotion =10 Segment 20CCAAC8: Total Size 876K,Allocated 872K,Free 0K minimum free space 0K,sweeps before promotion =10 Total Size 25792K,Allocated 22127K,Free 3310K