Limitare le dimensioni della cache del buffer in Linux


25

C'è un modo per dire al kernel Linux di usare solo una certa percentuale di memoria per la cache del buffer? So che /proc/sys/vm/drop_cachespuò essere utilizzato per cancellare temporaneamente la cache, ma esiste qualche impostazione permanente che ne impedisce la crescita oltre il 50% della memoria principale?

Il motivo per cui voglio fare questo è che ho un server che esegue un Ceph OSD che serve costantemente dati dal disco e riesce a utilizzare l'intera memoria fisica come cache buffer in poche ore. Allo stesso tempo, ho bisogno di eseguire applicazioni che alloceranno una grande quantità (diversi 10 GB di memoria) di memoria fisica. Contrariamente alla credenza popolare (consultare i consigli forniti su quasi tutte le domande relative alla cache del buffer), la liberazione automatica della memoria eliminando le voci della cache pulita non è istantanea: l'avvio della mia applicazione può richiedere fino a un minuto quando la cache del buffer è piena ( *), mentre dopo aver cancellato la cache (usando echo 3 > /proc/sys/vm/drop_caches) la stessa applicazione si avvia quasi istantaneamente.

(*) Durante questo minuto di avvio, l'applicazione presenta un errore nella nuova memoria ma trascorre il 100% del suo tempo nel kernel, secondo Vtune in una funzione chiamata pageblock_pfn_to_page. Questa funzione sembra essere correlata alla compattazione della memoria necessaria per trovare pagine enormi, il che mi porta a credere che il problema sia effettivamente la frammentazione.


1
C'è qualcosa chiamato tiering della cache. set di pool di ceph osd {cachepool} hit_set_count 1 set di pool di ceph osd {cachepool} hit_set_period 3600 set di pool di ceph osd {cachepool} target_max_bytes 100000000000000 come esempio vedi. docs.ceph.com/docs/master/rados/operations/cache-tiering
Michael D.

2
Dal momento che questo problema sembra riguardare solo l'avvio delle applicazioni ad alta intensità di memoria, forse potresti avviare le app tramite uno script che cancella la cache prima di avviarle effettivamente. Forse questo li avvia più velocemente lasciando comunque la gestione della cache al kernel mentre sono in esecuzione.
Thawn,

Risposte:


14

Se non vuoi un limite assoluto ma fai semplicemente pressione sul kernel per svuotare i buffer più velocemente, dovresti dare un'occhiata vm.vfs_cache_pressure

Questa variabile controlla la tendenza del kernel a recuperare la memoria utilizzata per la memorizzazione nella cache delle cache VFS, rispetto a pagecache e swap. L'aumento di questo valore aumenta la velocità con cui vengono recuperate le cache VFS.

Varia da 0 a 200. Spostalo verso 200 per una pressione maggiore. L'impostazione predefinita è 100. È inoltre possibile analizzare l'utilizzo della memoria utilizzando il slabtopcomando. Nel tuo caso, i valori dentrye *_inode_cachedevono essere alti.

Se vuoi un limite assoluto, dovresti cercare cgroups . Posizionare il server Ceph OSD in un cgroup e limitare la memoria massima che può utilizzare impostando il memory.limit_in_bytesparametro per il cgroup.

memory.memsw.limit_in_bytesimposta la quantità massima per la somma di memoria e l'utilizzo di swap. Se non viene specificata alcuna unità, il valore viene interpretato come byte. Tuttavia, è possibile utilizzare suffissi per rappresentare unità più grandi - k o K per kilobyte, m o M per Megabyte e ge G per Gigabyte.

Riferimenti:

[1] - Ottimizzazione del kernel di GlusterFS Linux

[2] - Guida alla gestione delle risorse di RHEL 6


1
Un cgroup con limit_in_bytesset sembra farlo. Grazie!
Wim,

4
Penso che vfs_cache_pressurecancella solo le cache di odontoiatria e inode e non ha nulla a che fare con la cache del buffer.
kawing-chiu,

L'aumento vfs_cache_pressuresopra 100può essere utile nel caso in cui non si disponga di RAM sufficiente per il carico di lavoro. Ridurrà l'utilizzo della RAM ma causerà prestazioni di I / O complessivamente inferiori.
Mikko Rantalainen,

3

Non conosco A% ma, puoi impostare un limite di tempo in modo che lo lasci cadere dopo x quantità di minuti.

Primo in un terminale

sync && echo 3 | sudo tee /proc/sys/vm/drop_caches

Per cancellare le cache correnti.

Rendilo a cron-job Premi Alt-F2, digita gksudo gedit /etc/crontab, quindi aggiungi questa riga nella parte inferiore.

 */15 *    * * *   root    sync && echo 3 > /proc/sys/vm/drop_caches

Questo pulisce ogni 15 minuti. Se lo desideri, puoi impostare 1 o 5 minuti modificando il primo parametro in * o * / 5 anziché * / 15

Per visualizzare la RAM libera, ad eccezione della cache:

free -m | sed -n -e '3p' | grep -Po "\d+$

Mi sento un po 'ridondante. Per quanto ne so, 3 > drop_cachesinclude il comportamento disync
andras.tim

1
@ andras.tim no - sync scrive le pagine sporche sul disco, 3 in drop_caches recupera / libera solo la memoria utilizzata da pagine pulite e altre cache. non è necessario eseguire la sincronizzazione, ma se lo fai, più memoria sarà pulita anziché sporca e più memoria verrà liberata quando si rilasciano cache
Daniel S. Sterling,

2

Penso che il tuo sospetto alla fine della tua domanda sia sulla buona strada. Sospetterei che A, allocazione di memoria consapevole di NUMA che migra pagine tra le CPU, o B, più probabilmente, il codice di deframmentazione di hugepage trasparenti che provano a trovare regioni allineate contigue.

Hugepages e hugepages trasparenti sono stati identificati sia per marcati miglioramenti delle prestazioni su determinati carichi di lavoro, sia per il consumo di enormi quantità di tempo della CPU senza fornire molti vantaggi.

Sarebbe utile sapere quale kernel stai eseguendo, il contenuto di / proc / meminfo (o almeno i valori di HugePages_ *.) E, se possibile, più del callgraph del profiler vtune che fa riferimento a pageblock_pfn_to_page ().

Inoltre, se desideri indovinare la mia ipotesi, prova a disabilitare la deframmentazione di hugepage con:

echo 'never'> / sys / kernel / mm / transparent_hugepage / defrag

(potrebbe essere invece questo, a seconda del kernel :)

echo 'never'> / sys / kernel / mm / redhat_transparent_hugepage / defrag

Infine, questa app usa molte decine di concerti di ram che hai scritto? Quale lingua?

Dato che hai usato il termine "errore nelle pagine di memoria", immagino che tu abbia abbastanza familiarità con il design operativo e la memoria virtuale. Faccio fatica a immaginare una situazione / applicazione che si guasterebbe in modo così aggressivo da non leggere in molti I / O - quasi sempre dalla cache del buffer che stai cercando di limitare.

(Se sei curioso, dai un'occhiata ai flag mmap (2) come MAP_ANONYMOUS e MAP_POPULATE e mincore (2) che possono essere usati per vedere quali pagine virtuali hanno effettivamente una pagina fisica mappata.)

In bocca al lupo!


2

Se Ceph OSD è un processo separato, è possibile utilizzare cgroups per controllare le risorse utilizzate dal processo:

Crea un cgroup chiamato come group1 con un limite di memoria (ad esempio di 50 GB, sono supportati altri limiti come CPU, ad esempio anche CPU):

cgcreate -g memory,cpu:group1

cgset -r memory.limit_in_bytes=$((50*1024*1024*1024)) group1

Quindi, se l'app è già in esecuzione, porta l'app in questo cgroup:

cgclassify -g memory,cpu:group1 $(pidof your_app_name)

O esegui la tua app all'interno di questo cgroup:

cgexec -g memory,cpu:group1 your_app_name

0

tuned è un demone di adattamento dinamico del sistema adattivo che sintonizza dinamicamente le impostazioni del sistema in base all'utilizzo.

 $ man tuned

Vedere la documentazione relativa e i file di configurazione.

 /etc/tuned
 /etc/tuned/*.conf
 /usr/share/doc/tuned-2.4.1
 /usr/share/doc/tuned-2.4.1/TIPS.txt

This parameter may be useful for you.

** Set flushing to once per 5 minutes
** echo "3000" > /proc/sys/vm/dirty_writeback_centisecs

Informazioni addizionali

Il comando sync svuota il buffer, cioè forza tutti i dati non scritti da scrivere su disco e può essere usato quando si vuole essere sicuri che tutto sia scritto in modo sicuro. Nei sistemi UNIX tradizionali, c'è un programma chiamato update in esecuzione in background che esegue una sincronizzazione ogni 30 secondi, quindi di solito non è necessario utilizzare la sincronizzazione. Linux ha un demone aggiuntivo, bdflush , che esegue una sincronizzazione più imperfetta più frequentemente per evitare il blocco improvviso a causa di pesanti I / O su disco che a volte la sincronizzazione provoca.

Sotto Linux, bdflush viene avviato dall'aggiornamento. Di solito non c'è motivo di preoccuparsene, ma se bdflush muore per qualche motivo, il kernel lo avviserà e dovresti avviarlo manualmente ( / sbin / update ).


1
Non è solo per voci sporche? Non penso che questo sia il problema sul mio sistema in quanto sono tutti puliti: il ritardo non è nel riscrivere pagine sporche ma nello spazio di deframmentazione lasciato rimuovendo quelle pulite.
Wim,

Sì, questo è per le pagine sporche, penso che puoi anche correggere altri problemi di prestazioni impostando la modalità dinamica.
Ijaz Ahmad Khan,

"A partire da Linux 2.6, la chiamata di sistema [bdflush] è obsoleta e non fa nulla. È probabile che scompaia del tutto in una futura versione del kernel. Oggi l'attività svolta da bdflush () è gestita dal thread pdflush del kernel." man7.org/linux/man-pages/man2/bdflush.2.html
sourcejedi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.