Haskell 哈斯克尔惰性卸载
我需要有一个大的数据列表,当在特定位置引用时,这些数据将计算(从文件加载,和/或在尚未生成文件时生成)并保存以备将来使用。这是由绑定到函数的惰性列表提供支持的。这些“块”有时被加载,但此后从未真正使用过,同时仍然在代码中有效引用,因此GC不会对它们进行处理Haskell 哈斯克尔惰性卸载,haskell,lazy-loading,lazy-evaluation,Haskell,Lazy Loading,Lazy Evaluation,我需要有一个大的数据列表,当在特定位置引用时,这些数据将计算(从文件加载,和/或在尚未生成文件时生成)并保存以备将来使用。这是由绑定到函数的惰性列表提供支持的。这些“块”有时被加载,但此后从未真正使用过,同时仍然在代码中有效引用,因此GC不会对它们进行处理 由于RAM很快就填满了,我想在一段时间后,在没有任何东西使用它们的情况下,懒洋洋地卸载这些块。这是可能的吗?您可以通过使用unsafeInterleaveIO读取区块,定期浏览列表并删除对长时间未使用的区块的引用来实现这一点(或者:使用@np
由于RAM很快就填满了,我想在一段时间后,在没有任何东西使用它们的情况下,懒洋洋地卸载这些块。这是可能的吗?您可以通过使用
unsafeInterleaveIO
读取区块,定期浏览列表并删除对长时间未使用的区块的引用来实现这一点(或者:使用@nponeccop在注释中建议的弱指针),但我会选择一些不依赖GC来管理块内存的东西(因为可预测的内存使用对您很重要)
例如:
import Data.HashTable.IO
type ChunkMap = BasicHashTable ChunkId (Maybe Chunk)
newChunkMap :: IO ChunkMap
getChunk :: ChunkMap -> IO Chunk
freeUnusedChunks :: ChunkMap -> IO ()
其中,getChunk
使用malloc
和freeUnusedChunks
为缺少的块分配内存,遍历该表并free
s未使用的块
您甚至可以在单独的线程中运行freeunsedchunks
:
freeThread = forever $ do
withChunkMapLock $ do
freeUnusedChunks map
threadDelay 5000000
你说的“懒散卸货”是什么意思?直到最后一刻才卸载?我怎么知道哪些块没有使用?将时间戳与每个块关联,并在每次访问时更新它。然后,您可以将最后N个时间戳保存在循环缓冲区中,也可以在
freeunsedchunks
中计算它们。那么弱指针(System.Mem.weak
frombase
)呢?它们在这里合适吗?@nponeccop当然可以使用一个包含弱指针的哈希表。如果缓存Haskell值,这将比我建议的更有用。缺点当然是将替换策略委托给GC,这可能是次优的。