问题描述
最近经常被问到一个问题,”为什么我们系统进程占用的物理内存(Res/Rss)会远远大于设置的Xmx值”,比如Xmx设置1.7G,但是top看到的Res的值却达到了3.0G,随着进程的运行,Res的值还在递增,直到达到某个值,被OS当做bad process直接被kill掉了。
1
2
3
4
5
6
7
|
top - 16:57:47 up 73 days, 4:12, 8 users, load average: 6.78, 9.68, 13.31
Tasks: 130 total, 1 running, 123 sleeping, 6 stopped, 0 zombie
Cpu(s): 89.9%us, 5.6%sy, 0.0%ni, 2.0%id, 0.7%wa, 0.7%hi, 1.2%si, 0.0%st
...
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
22753 admin 20 0 4252m 3.0g 17m S 192.8 52.7 151:47.59 /opt/taobao/java/bin/java -server -Xms1700m -Xmx1700m -Xmn680m -Xss256k -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseStringCache -XX:+
40 root 20 0 0 0 0 D 0.3 0.0 5:53.07 [kswapd0]
|
物理内存大于Xmx可能吗
先说下Xmx,这个vm配置只包括我们熟悉的新生代和老生代的最大值,不包括持久代,也不包括CodeCache,还有我们常听说的堆外内存从名字上一看也知道没有包括在内,当然还有其他内存也不会算在内等,因此理论上我们看到物理内存大于Xmx也是可能的,不过超过太多估计就可能有问题了。
物理内存和虚拟内存间的映射关系
我们知道os在内存上面的设计是花了心思的,为了让资源得到最大合理利用,在物理内存之上搞一层虚拟地址,同一台机器上每个进程可访问的虚拟地址空间大小都是一样的,为了屏蔽掉复杂的到物理内存的映射,该工作os直接做了,当需要物理内存的时候,当前虚拟地址又没有映射到物理内存上的时候,就会发生缺页中断,由内核去为之准备一块物理内存,所以即使我们分配了一块1G的虚拟内存,物理内存上不一定有一块1G的空间与之对应,那到底这块虚拟内存块到底映射了多少物理内存呢,这个我们在linux下可以通过/proc/<pid>/smaps
这个文件看到,其中的Size表示虚拟内存大小,而Rss表示的是物理内存,所以从这层意义上来说和虚拟内存块对应的物理内存块不应该超过此虚拟内存块的空间范围
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
8dc00000-100000000 rwxp 00000000 00:00 0
Size: 1871872 kB
Rss: 1798444 kB
Pss: 1798444 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 1798444 kB
Referenced: 1798392 kB
Anonymous: 1798444 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
|
此次为了排查这个问题,我特地写了个简单的分析工具来分析这个问题,将连续的虚拟内存块合并做统计,一般来说连续分配的内存块还是有一定关系的,当然也不能完全肯定这种关系,得到的效果大致如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
from->to vs rss rss_percentage(rss/total_rss) merge_block_count
0x8dc00000->0x30c9a20000 1871872 1487480 53.77% 1
0x7faf7a4c5000->0x7fffa7dd9000 1069464 735996 26.60% 440
0x7faf50c75000->0x7faf6c02a000 445996 226860 8.20% 418
0x7faf6c027000->0x7faf78010000 196452 140640 5.08% 492
0x418e8000->0x100000000 90968 90904 3.29% 1
0x7faf48000000->0x7faf50c78000 131072 35120 1.27% 4
0x7faf28000000->0x7faf3905e000 196608 20708 0.75% 6
0x7faf38000000->0x7faf4ad83000 196608 17036 0.62% 6
0x7faf78009000->0x7faf7a4c6000 37612 10440 0.38% 465
0x30c9e00000->0x30ca202000 3656 716 0.03% 5
0x7faf20000000->0x7faf289c7000 65536 132 0.00% 2
0x30c9a00000->0x30c9c20000 128 108 0.00% 1
0x30ca600000->0x30cae83000 2164 76 0.00% 5
0x30cbe00000->0x30cca16000 2152 68 0.00% 5
0x7fffa7dc3000->0x7fffa7e00000 92 48 0.00% 1
0x30cca00000->0x7faf21dba000 2148 32 0.00% 5
0x30cb200000->0x30cbe16000 2080
|