- Qual è la differenza tra "buffer" e l'altra cache?
- Perché vediamo questa distinzione in modo così evidente? (Possibile ragione storica)
- A cosa
Buffers
servono?
- Perché potremmo aspettarci
Buffers
in particolare di essere più o meno grandi?
1. Qual è la differenza tra "buffer" e l'altro tipo di cache?
Buffers
riporta la quantità di cache di pagina utilizzata per i dispositivi a blocchi. Il kernel deve sottrarre deliberatamente questo importo dal resto della cache della pagina quando segnala Cached
.
Vedi meminfo_proc_show () :
cached = global_node_page_state(NR_FILE_PAGES) -
total_swapcache_pages() - i.bufferram;
...
show_val_kb(m, "MemTotal: ", i.totalram);
show_val_kb(m, "MemFree: ", i.freeram);
show_val_kb(m, "MemAvailable: ", available);
show_val_kb(m, "Buffers: ", i.bufferram);
show_val_kb(m, "Cached: ", cached);
2. Perché vediamo questa distinzione in modo così evidente? (Possibile ragione storica)
La cache della pagina funziona in unità della dimensione della pagina MMU, in genere un minimo di 4096 byte. Questo è essenziale per l' mmap()
accesso ai file mappato in memoria. [1] [2] Viene utilizzato per condividere pagine del codice di libreria / programma caricato tra processi indipendenti e consentire il caricamento di singole pagine su richiesta. (Anche per scaricare pagine quando qualcos'altro ha bisogno di spazio e non sono state utilizzate di recente).
[1] I / O mappati in memoria - Il manuale della libreria GNU C.
[2] mmap
- Wikipedia.
I primi UNIX avevano una "cache buffer" di blocchi del disco e non avevano mmap (). Apparentemente quando mmap () è stato aggiunto per la prima volta, hanno semplicemente bloccato la cache della pagina in cima alla cache del buffer. Questo è disordinato come sembra. Alla fine, il sistema operativo basato su UNIX si è sbarazzato della cache del buffer. Quindi ora tutta la cache dei file è in unità di pagine. Le pagine vengono cercate per (file, offset), non per posizione sul disco. Questo è stato chiamato "cache buffer unificata", forse perché le persone avevano più familiarità con "cache buffer". [3]
[3] UBC: un efficiente sottosistema unificato di I / O e memorizzazione nella cache di memoria per NetBSD
"Una svolta interessante che Linux aggiunge è che i numeri di blocco del dispositivo in cui una pagina è memorizzata su disco sono memorizzati nella cache con la pagina sotto forma di un elenco di buffer_head
strutture. Quando una pagina modificata deve essere riscritta su disco, l'I / O le richieste possono essere inviate immediatamente al driver del dispositivo, senza la necessità di leggere alcun blocco indiretto per determinare dove devono essere scritti i dati della pagina. "[3]
In Linux 2.2 c'era una "cache buffer" separata usata per le scritture, ma non per le letture. "La cache della pagina ha utilizzato la cache del buffer per riscrivere i suoi dati, necessitando di una copia aggiuntiva dei dati e raddoppiando i requisiti di memoria per alcuni carichi di scrittura" (?). [4] Non preoccupiamoci troppo dei dettagli, ma questa storia sarebbe uno dei motivi per cui Linux ne segnala l' Buffers
utilizzo separatamente.
[4] Sostituzione della pagina nella gestione della memoria di Linux 2.4 , Rik van Riel.
Al contrario, in Linux 2.4 e versioni successive, la copia aggiuntiva non esiste. "Il sistema esegue l'IO del disco direttamente da e verso la pagina della cache della pagina." [4] Linux 2.4 è stato rilasciato nel 2001.
3. A cosa Buffers
servono?
I dispositivi a blocchi sono trattati come file e quindi hanno cache della pagina. Viene utilizzato "per i metadati del filesystem e la memorizzazione nella cache di dispositivi a blocchi grezzi". [4] Ma nelle attuali versioni di Linux, i filesystem non copiano il contenuto dei file attraverso di esso, quindi non c'è "doppia memorizzazione nella cache".
Penso alla Buffers
parte della cache della pagina come alla cache del buffer Linux. Sebbene alcune fonti potrebbero non essere d'accordo con questa terminologia.
La quantità di cache buffer utilizzata dal filesystem, se presente, dipende dai dettagli del file system specifico. Il sistema nella domanda utilizza ext4. ext3 / ext4 utilizzano la cache del buffer Linux per il journal, per i contenuti della directory e alcuni altri metadati.
Alcuni file system, inclusi ext3, ext4 e ocfs2, utilizzano il layer jbd o jbd2 per gestire il journaling dei blocchi fisici e questo layer utilizza fondamentalmente la cache del buffer.
- Articolo di posta elettronica di Ted Tso , 2013
Prima della versione 2.4 del kernel di Linux, Linux aveva cache di pagina e buffer separate. Dalla versione 2.4, la cache della pagina e del buffer sono unificate e Buffers
sono blocchi di dischi grezzi non rappresentati nella cache della pagina, ovvero non dati di file.
...
La cache del buffer rimane, tuttavia, poiché il kernel deve ancora eseguire l'I / O dei blocchi in termini di blocchi, non di pagine. Poiché la maggior parte dei blocchi rappresenta i dati dei file, la maggior parte della cache del buffer è rappresentata dalla cache della pagina. Ma una piccola quantità di dati di blocco non è supportata da file, ad esempio metadati e I / O a blocchi non elaborati, e quindi è rappresentata esclusivamente dalla cache del buffer.
- Una coppia di risposte Quora di Robert Love , ultimo aggiornamento 2013.
Entrambi gli autori sono sviluppatori Linux che hanno lavorato con la gestione della memoria del kernel Linux. La prima fonte è più specifica sui dettagli tecnici. La seconda fonte è un riassunto più generale, che potrebbe essere contraddetto e obsoleto in alcuni dettagli.
È vero che i filesystem possono eseguire scritture di metadati a pagina parziale, anche se la cache è indicizzata in pagine. Anche i processi utente possono eseguire scritture di pagine parziali quando usano write()
(al contrario di mmap()
), almeno direttamente su un dispositivo a blocchi. Questo vale solo per le scritture, non per le letture. Quando leggi la cache delle pagine, la cache delle pagine legge sempre le pagine intere.
A Linus piaceva affermare che la cache del buffer non è necessaria per eseguire scritture di dimensioni a blocchi e che i filesystem possono eseguire scritture di metadati a pagina parziale anche con cache di pagina collegata ai propri file anziché al dispositivo a blocchi. Sono sicuro che abbia ragione a dire che ext2 fa questo. ext3 / ext4 con il suo sistema di journaling no. È meno chiaro quali siano stati i problemi che hanno portato a questo progetto. Le persone a cui stava sfidando si stancarono di spiegare.
ext4_readdir () non è stato modificato per soddisfare il rant di Linus. Non vedo neanche il suo approccio desiderato usato in readdir () di altri filesystem. Penso che XFS usi anche la cache buffer per le directory. bcachefs non utilizza affatto la cache della pagina per readdir (); utilizza la propria cache per i btrees. Potrebbe mancare qualcosa in btrfs.
4. Perché potremmo aspettarci Buffers
in particolare di essere più o meno grandi?
In questo caso risulta che la dimensione del journal ext4 per il mio filesystem è 128M. Quindi questo spiega perché 1) la mia cache buffer può stabilizzarsi a poco più di 128M; 2) la cache buffer non si ridimensiona proporzionalmente con la maggiore quantità di RAM sul mio laptop.
Per alcune altre possibili cause, vedi Qual è la colonna buffer nell'output da libero? Si noti che i "buffer" segnalati in free
realtà sono una combinazione di Buffers
e memoria della lastra recuperabile.
Per verificare che le scritture di diario utilizzino la cache del buffer, ho simulato un filesystem in una RAM veloce (tmpfs) e ho confrontato l'utilizzo massimo del buffer per diverse dimensioni del diario.
# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=256
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size: 256M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
total used free shared buffers cache available
Mem: 7855 2521 4321 285 66 947 5105
Swap: 7995 0 7995
# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
total used free shared buffers cache available
Mem: 7855 2523 3872 551 237 1223 4835
Swap: 7995 0 7995
# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=16
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size: 16M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
total used free shared buffers cache available
Mem: 7855 2507 4337 285 66 943 5118
Swap: 7995 0 7995
# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
total used free shared buffers cache available
Mem: 7855 2509 4290 315 77 977 5086
Swap: 7995 0 7995
Storia di questa risposta: come sono arrivato a guardare il diario
Avevo trovato e-mail di Ted Tso prima, ed è stato incuriosito che ha sottolineato write cache. Troverei sorprendente se i dati "sporchi" e non scritti fossero in grado di raggiungere il 30% di RAM sul mio sistema. sudo atop
mostra che in un intervallo di 10 secondi, il sistema in questione scrive costantemente solo 1 MB. Il filesystem in questione sarebbe in grado di tenere il passo con oltre 100 volte questa velocità. (È su un disco rigido USB2, capacità massima ~ 20 MB / s).
L'uso di blktrace ( btrace -w 10 /dev/sda
) conferma che gli IO che vengono memorizzati nella cache devono essere scritti, poiché quasi non vengono letti dati. Inoltre questo mysqld
è l'unico processo di userspace che esegue IO.
Ho interrotto il servizio responsabile delle scritture (icinga2 scrivendo a mysql) e ricontrollato. Ho visto "buffer" scendere a meno di 20M - non ho spiegazioni per questo - e rimanere lì. Riavviando nuovamente il writer, i "buffer" aumentano di ~ 0,1 M per ogni intervallo di 10 secondi. Ho osservato che mantiene questo ritmo costantemente, risalendo a 70M e oltre.
La corsa echo 3 | sudo tee /proc/sys/vm/drop_caches
era sufficiente per abbassare nuovamente i "buffer", a 4,5M. Ciò dimostra che il mio accumulo di buffer è una cache "pulita", che Linux può rilasciare immediatamente quando richiesto. Questo sistema non sta accumulando dati non scritti . ( drop_caches
non esegue alcun writeback e quindi non può eliminare le pagine sporche. Se si desidera eseguire un test che ha prima pulito la cache, si utilizzerà il sync
comando).
L'intera directory mysql è solo 150M. I buffer di accumulo devono rappresentare blocchi di metadati dalle scritture mysql, ma mi ha sorpreso pensare che ci sarebbero così tanti blocchi di metadati per questi dati.