我正在使用这个简单的程序来确定GHC程序可以分配多少内存:
import System.Environment import Data.Set as Set main = do args <- getArgs let n = (read $args !! 0) :: Int s = Set.fromList [0..n] do putStrLn $"min: " ++ (show $findMin s) putStrLn $"max: " ++ (show $findMax s)
这是我发现的:
>运行./mem.exe 40000000 RTS -s成功并报告正在使用的总内存为1113 MB
>运行./mem.exe 42000000 RTS -s因内存不足错误而失败
>运行./mem.exe 42000000 RTS -s -M4G错误输出-M4G:大小超出允许范围
>运行./mem.exe 42000000 RTS -s -M3.9G因内存不足错误而失败
通过Windows任务管理器监视进程显示最大内存使用量约为1.2 GB.
我的系统:Win7,8 GB RAM,Haskell平台2011.04.0.0,ghc 7.0.4.
我正在编译:ghc -O2 mem.hs -rtsopts
如何使用我所有可用的RAM?我错过了一些明显的东西吗
这样做的一个结果是,您不能使用超过4G – 1BLOCK的内存,因为作为size参数允许的最大值是HS_WORD_MAX:
decodeSize(rts_argv[arg],2,BLOCK_SIZE,HS_WORD_MAX) / BLOCK_SIZE;
使用32位字,HS_WORD_MAX = 2 ^ 32-1.
这解释了
running ./mem.exe 42000000 +RTS -s -M4G errors out with -M4G: size outside allowed range
因为decodeSize()将4G解码为2 ^ 32.
升级GHC后,此限制也将保留,直到最终发布64位GHC for Windows.
作为32位进程,用户模式虚拟地址空间限制为2或4 GB(取决于IMAGE_FILE_LARGE_ADDRESS_AWARE标志的状态),参见Memory limits for Windows Releases.
现在,您正在尝试构建一个包含4200万个4字节Ints的Set. Data.Set.Set每个元素有五个单词开销(构造函数,大小,左右子树指针,指向元素的指针),因此Set将占用大约0.94 GiB的内存(1.008’metric’GB).但是该进程使用大约两倍或更多(它需要垃圾收集空间,至少是活动堆的大小).
在我的64位Linux上运行程序,输入21000000(以弥补两倍大的Ints和指针),我得到
$./mem +RTS -s -RTS 21000000 min: 0 max: 21000000 31,330,814,200 bytes allocated in the heap 4,708,535,032 bytes copied during GC 1,157,426,280 bytes maximum residency (12 sample(s)) 13,669,312 bytes maximum slop 2261 MB total memory in use (0 MB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 59971 colls,0 par 2.73s 2.73s 0.0000s 0.0003s Gen 1 12 colls,0 par 3.31s 10.38s 0.8654s 8.8131s INIT time 0.00s ( 0.00s elapsed) MUT time 12.12s ( 13.33s elapsed) GC time 6.03s ( 13.12s elapsed) EXIT time 0.00s ( 0.00s elapsed) Total time 18.15s ( 26.45s elapsed) %GC time 33.2% (49.6% elapsed) Alloc rate 2,584,429,494 bytes per MUT second Productivity 66.8% of total user,45.8% of total elapsed
但是top报告只有1.1g内存使用 – 顶部,可能是任务管理器,只报告实时堆.
因此,似乎没有设置IMAGE_FILE_LARGE_ADDRESS_AWARE,您的进程仅限于2GB的地址空间,并且4200万集需要更多 – 除非您指定更小的最大或建议堆大小:
$./mem +RTS -s -M1800M -RTS 21000000 min: 0 max: 21000000 31,200 bytes allocated in the heap 3,551,201,872 bytes copied during GC 1,312 bytes maximum slop 1154 MB total memory in use (0 MB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 59971 colls,0 par 2.70s 2.70s 0.0000s 0.0002s Gen 1 12 colls,0 par 4.23s 4.85s 0.4043s 3.3144s INIT time 0.00s ( 0.00s elapsed) MUT time 11.99s ( 12.00s elapsed) GC time 6.93s ( 7.55s elapsed) EXIT time 0.00s ( 0.00s elapsed) Total time 18.93s ( 19.56s elapsed) %GC time 36.6% (38.6% elapsed) Alloc rate 2,611,793,025 bytes per MUT second Productivity 63.4% of total user,61.3% of total elapsed
将最大堆大小设置为低于它自然使用的大小,实际上让它适合于Set所需的空间,以较长的GC时间为代价,并且建议堆大小-H1800M让它完成仅使用
1831 MB total memory in use (0 MB lost due to fragmentation)
因此,如果您指定最大堆大小低于2GB(但足够大以使Set适合),它应该工作.