我们build立了一个内存数据库,在一个Vec中吃了大约100-150G的内存,这个内存是这样的:
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中,此function的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实例上运行,并且透明的巨大页面已被禁用。
[~]$ 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
真正的问题是为什么这个function有那么多开销?
这似乎是一个操作系统的问题,而不是这个特定的防锈功能的问题。
大多数操作系统(包括Linux)都使用按需分页 。 默认情况下,Linux不会为新分配的内存分配物理页面。 相反,它将为所有分配的内存分配一个具有只读权限的零页面(即,所有的虚拟内存页面将指向这个单一的物理内存页面)。
如果您尝试写入内存,则会发生页面错误,将分配一个新页面,并将相应地设置权限。
我猜你正在程序中看到这种效果。 如果你尝试第二次做同样的事情,它应该快得多。 还有一些方法可以通过sysctl
来控制这个策略: https : //www.kernel.org/doc/Documentation/vm/overcommit-accounting 。
不知道为什么禁用THP,但在这种情况下,大页面可能会帮助您,因为每个大页面(2Mib)会发生一次保护更改,而不是每页正常页面(4KiB)发生一次。