usenuma做了什么?(2012-03-14)
DESCRIPTION
UseNUMA在JDK6/Linux上的实现TRANSCRIPT
Kris Mok, Software Engineer, Taobao@rednaxelafx莫枢 /“ 撒迦”
UseNUMA 做了什么?
JDK6/Linux 中的 HotSpot VM 实现
阿里巴巴集团 - 技术共享平台 -
核心系统研发 - 专用计算组莫枢(撒迦)2012-03-14
UseNUMA 的有效范围• JDK 6 / Linux 上:
– 硬件是 NUMA 架构的; BIOS 打开了 NUMA 选项– Xen 等虚拟层的 NUMA 选项打开(如有)– 操作系统的 NUMA 选项打开
• 请检查 /sys/devices/system/node/• 可通过 numastat的输出判断 JVM 以下各层是否都设置正确
– 只要有设置不正确的就只能看到 1个 node
– libnuma.so.1 存在并且可加载• 无法加载到该库会使 UseNUMA = false
– -XX:+UseParallelGC / -XX:+UseParallelOldGC• JDK6 的 HotSpot VM 的其它 GC 未实现 NUMA 支持
– -XX:+ForceNUMA• 强制打开 UseNUMA,但并不代表就会变快
UseNUMA 的有效范围(续)
$ numastat node0 node1numa_hit 619315854 14453914507numa_miss 75245098 9049098780numa_foreign 9049098780 75245098interleave_hit 657266 752980local_node 618174068 14452713656other_node 76386884 9050299631
UseNUMA 的有效范围(续)
• 确认 UseNUMA 的开启:– jinfo –flag UseNUMA <pid>• 正确开启时显示: -XX:+UseNUMA• 未开启时显示: -XX:-UseNUMA
UseNUMA 的有效范围(续)
• Bug 7060836:– RHEL 5.5 and 5.6 don't support UseNUMA
because the locality group id implementation is done via a call to sched_getcpu(), which was introduced in only in recent versions of libc. In the case of RHEL 5.5 and 5.6, Hotspot cannot find sched_getcpu and UseNUMA is disabled.
– RHEL 5.4 同样受影响– 在 JDK7u2 有修复;淘宝 JDK6u32 有移植该修复
UseNUMA 的实现• JVM 的 GC heap 初始化时
– eden 空间的布局会适应 NUMA 拓扑• 由 MutableNUMASpace实现• 根据 locality group 将地址空间划分为若干块• 每个 locality group 有一块独立的分配空间
– 称为 LGRPSpace
• 每个 LGRPSpace所包含的 page 在指定的 locality group 上分配物理内存– MutableNUMASpace::bias_region()– => numa_tonode_memory()
– 其它空间不受 NUMA 拓扑影响• survivor spaces 、 old generation 、 permanent
generation 默认使用 interleaved 方式分配内存,不偏向任何locality group
实验例子参考资料
UseNUMA 的实现(续)普通的 ParallelScavengeHeap布局Heap
PSYoungGen total 150208K, used 59114K [0x0000000758600000, 0x0000000762da0000, 0x0000000800000000) eden space 128768K, 38% used [0x0000000758600000,0x000000075b6ac8d8,0x00000007603c0000) from space 21440K, 43% used [0x00000007603c0000,0x0000000760cce0d0,0x00000007618b0000) to space 21440K, 0% used [0x00000007618b0000,0x00000007618b0000,0x0000000762da0000) ParOldGen total 343296K, used 0K [0x0000000609200000, 0x000000061e140000, 0x0000000758600000) object space 343296K, 0% used [0x0000000609200000,0x0000000609200000,0x000000061e140000) PSPermGen total 21248K, used 16956K [0x0000000604000000, 0x00000006054c0000, 0x0000000609200000) object space 21248K, 79% used [0x0000000604000000,0x000000060508f390,0x00000006054c0000)
UseNUMA 的实现(续)604000000 default anon=5312 dirty=5312 N1=5312
6054c0000 default
609200000 default anon=85824 dirty=85824 N1=85824
61e140000 default
758600000 default anon=42912 dirty=42912 N1=42912
762da0000 default (日志来自 /proc/<pid>/numa_maps )
Permanent Generation (commited)
Permanent Generation (reserved)
Old Generation (reserved)
Young Generation (reserved)
Young Generation (commited)
Old Generation (commited)
UseNUMA 的实现(续)使用 -XX:+UseNUMA的ParallelScavengeHeap布局
Heap PSYoungGen total 150208K, used 24082K [0x0000000758600000, 0x0000000762da0000, 0x0000000800000000) eden space 128768K, 11% used [0x0000000758600000,0x000000075d122cc8,0x00000007603c0000) lgrp 0 space 64384K, 4% used [0x0000000758600000,0x0000000758883d98,0x000000075c4e0000) local/remote/unbiased/uncommitted: 0K/0K/0K/0K, large/small pages: 0/0 lgrp 1 space 64384K, 19% used [0x000000075c4e0000,0x000000075d122cc8,0x00000007603c0000) local/remote/unbiased/uncommitted: 0K/0K/0K/0K, large/small pages: 0/0 from space 21440K, 41% used [0x00000007603c0000,0x0000000760c7e0b0,0x00000007618b0000) to space 21440K, 0% used [0x00000007618b0000,0x00000007618b0000,0x0000000762da0000) ParOldGen total 343296K, used 0K [0x0000000609200000, 0x000000061e140000, 0x0000000758600000) object space 343296K, 0% used [0x0000000609200000,0x0000000609200000,0x000000061e140000) PSPermGen total 21248K, used 16790K [0x0000000604000000, 0x00000006054c0000, 0x0000000609200000) object space 21248K, 79% used [0x0000000604000000,0x00000006050659a0,0x00000006054c0000)
UseNUMA 的实现(续)604000000 interleave=0-1 anon=4185 dirty=4185 N0=2093 N1=2092
6054c0000 default
609200000 interleave=0-1
61e140000 default
758600000 bind=0 anon=16096 dirty=16096 N0=16096
75c4e0000 bind=1 anon=16096 dirty=16096 N1=16096
7603c0000 interleave=0-1 anon=2239 dirty=2239 active=2215 N0=1120 N1=1119
7618b0000 interleave=0-1
762da0000 default
Permanent Generation (commited)
Permanent Generation (reserved)
Old Generation (commited)
Old Generation (reserved)
LGRPSpace (lgrp_id=0)
LGRPSpace (lgrp_id=1)
Survivor Space 0 (commited)
Survivor Space 1 (commited)
Young Generation (reserved)
使用 -XX:+UseNUMA的ParallelScavengeHeap布局
UseNUMA 的实现(续)• Java 线程启动时– 记录线程所在的 CPU 对应的 locality group
id
• 外部线程 attach 到 JVM 时– 同上
UseNUMA 的实现(续)• Java 程序正常运行时– 每个 locality group 的线程在各自的LGRPSpace 中分配空间• 每个线程在自己的 TLAB 里分配空间给 Java 对象• 每个线程的 TLAB 都只在所属的 locality group 的LGRPSpace 里分配– MutableNUMASpace::allocate()– 每次分配 TLAB 会重新记录当前线程的 lgrp_id ,以便适
应线程在不同 locality group 之间的迁移• 没有“ shared eden”
– 每当有 LGRPSpace 填满了就触发一次 minor GC
UseNUMA 的实现(续)• ( Linux 上不支持) NUMA 拓扑发生变化
时– 所有 Java 线程的 locality group id 被清除• MutableNUMASpace::update_layout()
– 每个线程在之后第一次尝试分配空间时重新记录 local group id• MutableNUMASpace::allocate()• MutableNUMASpace::cas_allocate()
QUESTIONS?
Kris Mok, Software Engineer, Taobao@rednaxelafx莫枢 /“ 撒迦”