2015-10-03 15 views
11

Abbiamo costruito un database di memoria, che mangia circa 100-150G RAM in un unico Vec, che è popolata in questo modo:Perché la CPU `change_protection` gira mentre carica una grande quantità di dati nella RAM?

let mut result = Vec::with_capacity(a_very_large_number); 
while let Ok(n) = reader.read(&mut buffer) { 
    result.push(...); 
} 

perf top mostra che il tempo è in gran parte speso in questa funzione "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     [.] [email protected] 

L'utilizzo della CPU di questa funzione cresce come sempre più dati vengono caricati nella RAM:

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 

Il codice è in esecuzione su un'istanza AWS EC2 r3.8xlarge e la pagina enorme trasparente è già disabilitata.

[~]$ 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: 

kernel

3.14.35-28.38.amzn1.x86_64 

la vera domanda è perché c'è così tanto in testa in quella funzione?

+1

Quale kernel stai utilizzando? Sto usando 4.2.5 e ho un problema simile con mongod. Con l'aumentare della memoria residente di mongod, la CPU impiegata in change_protection aumenta. Se questo problema si riproduce in ruggine e mongod ma non in versioni molto diverse del kernel, potrebbe trattarsi di un problema del kernel invece di un problema ruggine o mongod. Il kernel – Syncopated

+1

è incluso nel post, ho provato a convertire il programma in c, ottenere lo stesso problema. http://stackoverflow.com/questions/33257404/why-update-big-array-makes-change-protection-kernel-call-dominating-cpu – Dapeng

+1

Il problema si ripropone se si blocca il processo su un core? Forse sperimentare opzioni numactl? Il mio problema con mongod scompare quando lo eseguo con numactl --interleave = all. – Syncopated

risposta

1

Questo sembra essere un problema di sistema operativo, piuttosto che un problema con questa funzione specifica di ruggine.

La maggior parte dei sistemi operativi (incluso Linux) utilizza demand paging. Per impostazione predefinita, Linux non allocherà pagine fisiche per la memoria appena assegnata. Invece assegnerà una singola pagina zero con permessi di sola lettura per tutta la memoria allocata (ad esempio, tutte le pagine di memoria virtuale punteranno a questa singola pagina di memoria fisica).

Se si tenta di scrivere nella memoria, si verificherà un errore di pagina, verrà assegnata una nuova pagina e le autorizzazioni verranno impostate di conseguenza.

Immagino che tu stia vedendo questo effetto nel tuo programma. Se provi a fare la stessa cosa una seconda volta, dovrebbe essere molto più veloce. Esistono anche modi per controllare questa politica tramite sysctl: https://www.kernel.org/doc/Documentation/vm/overcommit-accounting.

Non sai perché hai disattivato THP, ma in questo caso le pagine di grandi dimensioni potrebbero aiutarti poiché la modifica della protezione avverrà una volta per ogni pagina di grandi dimensioni (2Mib) anziché una volta per pagina normale (4 KB).

Problemi correlati