我们已经构建了一个内存数据库,它在一个Vec中占用大约100-150G RAM,其填充方式如下:
let mut result = Vec::with_capacity(a_very_large_number);
while let Ok(n) = reader.read(&mut buffer) {
result.push(...);
}
perf top
表明时间大部分用于此“change_protection”功能:
Samples: 48K of event 'cpu-clock', Event count (approx.): 694742858
62.45% [kernel] [k] change_protection
18.18% iron [.] database::Database::init::h63748
7.45% [kernel] [k] vm_normal_page
4.88% libc-2.17.so [.] __memcpy_ssse3_back
0.92% [kernel] [k] copy_user_enhanced_fast_string
0.52% iron [.] memcpy@plt
随着越来越多的数据加载到RAM中,此函数的CPU使用率也在增长:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12383 iron 20 0 137g 91g 1372 D 76.1 37.9 27:37.00 iron
代码在r3.8xlarge AWS EC2实例上运行,透明的hugepage已被禁用。
[~]$ cat /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]
[~]$ cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
cpuinfo中
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 62
model name : Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz
stepping : 4
microcode : 0x428
cpu MHz : 2500.070
cache size : 25600 KB
physical id : 0
siblings : 16
core id : 0
cpu cores : 8
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm xsaveopt fsgsbase smep erms
bogomips : 5000.14
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
内核
3.14.35-28.38.amzn1.x86_64
真正的问题是为什么这个功能有这么多的开销?
答案 0 :(得分:1)
这似乎是操作系统问题,而不是这个特定生锈功能的问题。
大多数操作系统(包括Linux)使用demand paging。默认情况下,Linux不会为新分配的内存分配物理页面。相反,它将为所有分配的内存分配一个具有只读权限的零页面(即,所有虚拟内存页面将指向此单个物理内存页面)。
如果您尝试写入内存,将发生页面错误,将分配新页面,并相应地设置其权限。
我猜你在你的程序中看到了这种效果。如果你第二次尝试做同样的事情,那应该快得多。还有一些方法可以通过sysctl
:https://www.kernel.org/doc/Documentation/vm/overcommit-accounting来控制此政策。
不确定禁用THP的原因,但在这种情况下,大页面可能对您有所帮助,因为每个大页面(2Mib)都会发生一次保护更改,而不是每个普通页面(4KiB)发生一次。