cs240:recDir 在两种类似情况下使用的额外 150 MB
cs240: the extra 150 MB used by recDir under two similar circumstances
我正在浏览 Functional Systems in Haskell 的幻灯片。在那堂课中,定义了一个函数 recDir2
,它使用 unsafeInterleaveIO
递归地列出目录中的所有文件:
import qualified Data.ByteString.Lazy as L
recDir2 :: FilePath -> IO [FilePath]
recDir2 dir = do
ds <- openDirStream dir
let protect m = m `onException` closeDirStream ds
nextName = unsafeInterleaveIO $
protect (readDirStream ds) >>= checkName
checkName "" = closeDirStream ds >> return []
checkName "." = nextName
checkName ".." = nextName
checkName name = getSymbolicLinkStatus path >>= checkStat path
where path = dir </> name
checkStat path stat
| isRegularFile stat = liftM (path :) nextName
| isDirectory stat =
liftM2 (++) (protect $ recDir2 path) nextName
| otherwise = nextName
nextName
在哪里
readFiles :: [FilePath] -> IO L.ByteString
readFiles [] = return L.empty
readFiles (f:fs) = liftM2 L.append (L.readFile f)
(unsafeInterleaveIO $ readFiles fs)
后面两种看似相等的情况都会用到这个函数:
*Main> recDir2 "/usr/include" >>= readFiles >>= print . L.length
*Main> x <- recDir2 "/usr/include" >>= readFiles
*Main> L.length x
然而在幻灯片中说第二种情况使用额外的 150 MB,但我看不出原因。是什么导致了这种所谓的额外内存使用?
将此与以下内容进行比较:
> let xs = [1..999999999]
> length xs
和
> length [1..999999999]
在第二种情况下,垃圾收集器可以在列表被使用时清理它,因此您使用的内存非常少。但在第一种情况下,您仍然持有对 xs
的引用,并且您可以随时输入 xs !! 555
。所以垃圾收集器必须为你在内存中保留 xs
的全部内容。
同样在您的示例中,一个版本引用了 x
,以后可能会重复使用,因此必须保留 x
的内容。
我正在浏览 Functional Systems in Haskell 的幻灯片。在那堂课中,定义了一个函数 recDir2
,它使用 unsafeInterleaveIO
递归地列出目录中的所有文件:
import qualified Data.ByteString.Lazy as L
recDir2 :: FilePath -> IO [FilePath]
recDir2 dir = do
ds <- openDirStream dir
let protect m = m `onException` closeDirStream ds
nextName = unsafeInterleaveIO $
protect (readDirStream ds) >>= checkName
checkName "" = closeDirStream ds >> return []
checkName "." = nextName
checkName ".." = nextName
checkName name = getSymbolicLinkStatus path >>= checkStat path
where path = dir </> name
checkStat path stat
| isRegularFile stat = liftM (path :) nextName
| isDirectory stat =
liftM2 (++) (protect $ recDir2 path) nextName
| otherwise = nextName
nextName
在哪里
readFiles :: [FilePath] -> IO L.ByteString
readFiles [] = return L.empty
readFiles (f:fs) = liftM2 L.append (L.readFile f)
(unsafeInterleaveIO $ readFiles fs)
后面两种看似相等的情况都会用到这个函数:
*Main> recDir2 "/usr/include" >>= readFiles >>= print . L.length
*Main> x <- recDir2 "/usr/include" >>= readFiles
*Main> L.length x
然而在幻灯片中说第二种情况使用额外的 150 MB,但我看不出原因。是什么导致了这种所谓的额外内存使用?
将此与以下内容进行比较:
> let xs = [1..999999999]
> length xs
和
> length [1..999999999]
在第二种情况下,垃圾收集器可以在列表被使用时清理它,因此您使用的内存非常少。但在第一种情况下,您仍然持有对 xs
的引用,并且您可以随时输入 xs !! 555
。所以垃圾收集器必须为你在内存中保留 xs
的全部内容。
同样在您的示例中,一个版本引用了 x
,以后可能会重复使用,因此必须保留 x
的内容。