目前,在 Windows 上,GHC 是 32 位 GHC - 我认为 Windows 的 64 位 GHC 应该在 7.6 到来时可用。
这样做的一个结果是,在 Windows 上,您不能使用超过4G - 1BLOCK
内存,因为允许作为大小参数的最大值是HS_WORD_MAX
:
decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_WORD_MAX) / BLOCK_SIZE;
对于 32 位字,HS_WORD_MAX = 2^32-1
.
这解释了
运行 ./mem.exe 42000000 +RTS -s -M4G 使用 -M4G 出错:大小超出允许范围
因为decodeSize()
解码4G
为2^32
.
在升级您的 GHC 后,此限制也将继续存在,直到最终发布适用于 Windows 的 64 位 GHC。
作为 32 位进程,用户模式虚拟地址空间限制为 2 或 4 GB(取决于IMAGE_FILE_LARGE_ADDRESS_AWARE
标志的状态),参见Windows 版本的内存限制。
现在,您正在尝试构造一个Set
包含 4200 万个 4 字节Int
的 s。AData.Set.Set
每个元素有五个字的开销(构造函数、大小、左右子树指针、指向元素的指针),因此Set
将占用大约 0.94 GiB 的内存(1.008 'metric' GB)。但是该进程使用了大约两倍或更多(它需要用于垃圾收集的空间,至少是活动堆的大小)。
在我的 64 位 linux 上运行程序,输入 21000000 (以弥补两倍大Int
的 s 和指针),我得到
$ ./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
内存使用 -top
并且可能是任务管理器,仅报告实时堆。
所以似乎IMAGE_FILE_LARGE_ADDRESS_AWARE
没有设置,您的进程被限制为 2GB 的地址空间,而 4200 万Set
需要更多 - 除非您指定的最大或建议的堆大小更小:
$ ./mem +RTS -s -M1800M -RTS 21000000
min: 0
max: 21000000
31,330,814,200 bytes allocated in the heap
3,551,201,872 bytes copied during GC
1,157,426,280 bytes maximum residency (12 sample(s))
13,669,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
以适应),它应该可以工作。