【问题标题】:Haskell lazy unloadingHaskell 延迟卸载
【发布时间】:2012-10-24 08:53:45
【问题描述】:

我需要有一个大的数据列表,当在特定位置引用时计算(从文件加载,和/或在尚未生成时生成它)并保留它以供将来使用。这是由绑定到函数的惰性列表提供支持的。这些“块”有时会被加载,但此后从未真正使用过,但仍会在代码中有效地引用,因此 GC 不会接收到它们。

由于 RAM 很快就会被填满,我想在一段时间没有任何东西使用这些块之后,懒惰地卸载这些块。这可能吗?

【问题讨论】:

  • “懒卸载”是什么意思?直到最后一刻才卸货?

标签: haskell lazy-loading lazy-evaluation


【解决方案1】:

您可以通过使用unsafeInterleaveIO 读取块并定期遍历列表并删除对长时间未使用的块的引用来实现这一点(或者:使用弱指针作为 @nponeccop 在 cmets 中建议),但我会选择不依赖 GC 来管理块内存的东西(因为可预测的内存使用对你很重要)。

例如:

import Data.HashTable.IO

type ChunkMap = BasicHashTable ChunkId (Maybe Chunk)

newChunkMap :: IO ChunkMap
getChunk :: ChunkMap -> IO Chunk
freeUnusedChunks :: ChunkMap -> IO ()

getChunk 为缺少的块分配内存,mallocfreeUnusedChunks 遍历表,frees 未使用的块。

您甚至可以在单独的线程中运行freeUnusedChunks

freeThread = forever $ do
                 withChunkMapLock $ do
                     freeUnusedChunks map
                     threadDelay 5000000

【讨论】:

  • 我怎么知道哪些没有使用?
  • 将时间戳与每个块相关联,并在每次访问时更新它。然后,您可以将最后 N 个时间戳保存在循环缓冲区中,也可以在 freeUnusedChunks 中计算它们。
  • 弱指针(System.Mem.Weak 来自base)呢?他们在这里合适吗?
  • @nponeccop 好吧,当然可以使用填充了弱指针的哈希表。如果缓存 Haskell 值,那将比我建议的更有用。缺点当然是把替换策略委托给 GC,这可能不是最佳的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-03
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2013-03-06
  • 1970-01-01
  • 2016-07-07
相关资源
最近更新 更多