我在Raspberry Pi3 B +的1GB物理内存中使用dphys-swapfile
设置了4GB交换文件。默认值为100MB。我正在运行一个go应用程序,其内存使用量有时达到1.2GB左右。但是,即使有4GB交换内存,此峰值也会导致OOM错误:
runtime: out of memory: cannot allocate 137035776-byte block (1053458432 in use)
fatal error: out of memory
runtime stack:
runtime.throw(0x6a2e8e, 0xd)
/usr/local/go/src/runtime/panic.go:616 +0x60
runtime.largeAlloc(0x82ab0fc, 0x101, 0x11160b60)
/usr/local/go/src/runtime/malloc.go:828 +0xdc
runtime.mallocgc.func1()
/usr/local/go/src/runtime/malloc.go:721 +0x38
runtime.systemstack(0x0)
/usr/local/go/src/runtime/asm_arm.s:349 +0x80
runtime.mstart()
/usr/local/go/src/runtime/proc.go:1175
为什么malloc会忽略可用的交换空间?
root@raspberrypi:~# sysctl vm.swappiness
vm.swappiness = 100
root@raspberrypi:~# sysctl vm.overcommit_memory
vm.overcommit_memory = 1
root@raspberrypi:~# free
total used free shared buff/cache available
Mem: 949452 36448 847880 1148 65124 862884
Swap: 4194300 30464 4163836
root@raspberrypi:~# cat /proc/meminfo
MemTotal: 949452 kB
MemFree: 847880 kB
MemAvailable: 862900 kB
Buffers: 10476 kB
Cached: 46848 kB
SwapCached: 872 kB
Active: 32140 kB
Inactive: 37728 kB
Active(anon): 10008 kB
Inactive(anon): 3692 kB
Active(file): 22132 kB
Inactive(file): 34036 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 4194300 kB
SwapFree: 4163836 kB
Dirty: 20 kB
Writeback: 0 kB
AnonPages: 12072 kB
Mapped: 13024 kB
Shmem: 1148 kB
Slab: 18452 kB
SReclaimable: 7816 kB
SUnreclaim: 10636 kB
KernelStack: 888 kB
PageTables: 1140 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 4669024 kB
Committed_AS: 114252 kB
VmallocTotal: 1114112 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
CmaTotal: 8192 kB
CmaFree: 6780 kB
将vm.swappiness
设置为1,10,60,100或vm.overcommit_memory
对此OOM没有影响。
我的理解是操作系统会尝试从物理内存中交换尽可能多的数据,以避免OOM崩溃。但在这种情况下,它似乎只是忽略它。可能是什么原因?
完整性的ulimit值:
root@raspberrypi:~# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7345
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 7345
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
答案 0 :(得分:2)
如果您运行的是32位操作系统,则可能会出现内存碎片问题。很有可能达到甚至无法分配几兆字节的程度,因为每个可能的虚拟地址都充满了某些内容。
对于使用Java,.NET或Go等许多线程的语言来说,这尤其糟糕。每个线程都有自己的堆栈,如果需要的话,它可以放在某个地方。
与ASLR结合进行安全随机化,32位内存很快就会碎片化。
您也可以达到最大地图数量。这甚至会影响64位系统,但我没有看到它发生在Go上。 Rust打了很多。 Linux默认为64k映射。我在Linux系统上增加了它:
$ cat /etc/sysctl.d/20-max-maps.conf
vm.max_map_count = 262144