- ¿Cuál es la diferencia entre "búferes" y el otro tipo de caché?
- ¿Por qué esta distinción es tan prominente? ¿Por qué algunas personas dicen "caché de búfer" cuando hablan del contenido del archivo en caché?
- ¿Qué son
Buffers
? utilizado para? - ¿Por qué podríamos esperar
Buffers
en particular para ser más grande o más pequeño?
1. ¿Cuál es la diferencia entre "búferes" y el otro tipo de caché?
Buffers
muestra la cantidad de caché de página utilizada para dispositivos de bloque. Los "dispositivos de bloque" son el tipo más común de dispositivo de almacenamiento de datos.
El núcleo tiene que restar deliberadamente esta cantidad del resto de la memoria caché de la página cuando informa Cached
. Ver 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. ¿Por qué se hace tan prominente esta distinción? ¿Por qué algunas personas dicen "caché de búfer" cuando hablan del contenido del archivo en caché?
La memoria caché de la página funciona en unidades del tamaño de la página MMU, normalmente un mínimo de 4096 bytes. Esto es esencial para mmap()
, es decir, acceso a archivos mapeados en memoria.[1][2] Está diseñado para compartir páginas de código de programa / biblioteca cargado entre procesos separados y permite cargar páginas individuales a pedido. (También para descargar páginas cuando algo más necesita espacio y no se han utilizado recientemente).
[1] E/S mapeada en memoria:el manual de la biblioteca GNU C.
[2] mmap
-Wikipedia.
Los primeros UNIX tenían un "caché de búfer" de bloques de disco y no tenían mmap(). Aparentemente, cuando mmap() se agregó por primera vez, agregaron el caché de la página como una nueva capa en la parte superior. Esto es tan complicado como suena. Eventualmente, los sistemas operativos basados en UNIX se deshicieron del caché de búfer separado. Así que ahora todo el caché de archivos está en unidades de páginas. Las páginas se buscan por (archivo, desplazamiento), no por ubicación en el disco. Esto se denominó "caché de búfer unificado", quizás porque la gente estaba más familiarizada con "caché de búfer".[3]
[3] UBC:un subsistema de almacenamiento en caché de memoria y E/S unificado eficiente para NetBSD
("Un giro interesante que agrega Linux es que los números de bloque del dispositivo donde se almacena una página en el disco se almacenan en caché con la página en forma de una lista de buffer_head
estructuras Cuando una página modificada se va a volver a escribir en el disco, las solicitudes de E/S se pueden enviar al controlador del dispositivo de inmediato, sin necesidad de leer ningún bloque indirecto para determinar dónde se deben escribir los datos de la página".[3])
En Linux 2.2 había un "caché de búfer" separado que se usaba para escrituras, pero no para lecturas. "La caché de la página usó la caché del búfer para volver a escribir sus datos, necesitando una copia adicional de los datos y duplicando los requisitos de memoria para algunas cargas de escritura".[4] No nos preocupemos demasiado por los detalles, pero este historial sería una de las razones por las que Linux informa Buffers
uso por separado.
[4] Reemplazo de página en la gestión de memoria de Linux 2.4, Rik van Riel.
Por el contrario, en Linux 2.4 y superior, la copia adicional no existe. "El sistema realiza E/S de disco directamente hacia y desde la página de caché de la página".[4] Linux 2.4 se lanzó en 2001.
3. ¿Qué son Buffers
¿para qué?
Los dispositivos de bloque se tratan como archivos y, por lo tanto, tienen caché de página. Esto se usa "para los metadatos del sistema de archivos y el almacenamiento en caché de dispositivos de bloques sin formato".[4] Pero en las versiones actuales de Linux, los sistemas de archivos no copian el contenido de los archivos a través de él, por lo que no hay "doble almacenamiento en caché".
Pienso en el Buffers
parte de la caché de la página como la caché del búfer de Linux. Algunas fuentes pueden no estar de acuerdo con esta terminología.
La cantidad de caché de búfer que utiliza el sistema de archivos, si la hay, depende del tipo de sistema de archivos. El sistema en la pregunta usa ext4. ext3/ext4 usa el caché del búfer de Linux para el diario, para el contenido del directorio y algunos otros metadatos.
Ciertos sistemas de archivos, incluidos ext3, ext4 y ocfs2, usan la capa jbd o jbd2 para manejar su registro de bloque físico, y esta capa usa fundamentalmente el caché de búfer.
-- Artículo de correo electrónico de Ted Tso, 2013
Antes de la versión 2.4 del kernel de Linux, Linux tenía cachés de página y de búfer separados. Desde la versión 2.4, la página y el caché del búfer están unificados y Buffers
son bloques de disco sin procesar que no están representados en la memoria caché de la página, es decir, no son datos de archivo.
...
Sin embargo, la memoria caché del búfer permanece, ya que el kernel aún necesita realizar E/S de bloque en términos de bloques, no de páginas. Como la mayoría de los bloques representan datos de archivos, la mayor parte de la memoria caché del búfer está representada por la memoria caché de la página. Pero una pequeña cantidad de datos de bloque no está respaldada por archivos (metadatos y E/S de bloque sin formato, por ejemplo) y, por lo tanto, está representada únicamente por la memoria caché del búfer.
-- Un par de respuestas de Quora de Robert Love, actualizadas por última vez en 2013.
Ambos escritores son desarrolladores de Linux que han trabajado con la administración de memoria del kernel de Linux. La primera fuente es más específica sobre los detalles técnicos. La segunda fuente es un resumen más general, que puede contradecirse y estar desactualizado en algunos detalles.
Es cierto que los sistemas de archivos pueden realizar escrituras de metadatos de página parcial, aunque el caché esté indexado en páginas. Incluso los procesos de usuario pueden realizar escrituras de páginas parciales cuando usan write()
(a diferencia de mmap()
), al menos directamente a un dispositivo de bloque. Esto solo se aplica a las escrituras, no a las lecturas. Cuando lee el caché de la página, el caché de la página siempre lee páginas completas.
A Linus le gustaba despotricar que la memoria caché del búfer no es necesaria para realizar escrituras de tamaño de bloque, y que los sistemas de archivos pueden realizar escrituras de metadatos de página parcial incluso con la memoria caché de página adjunta a sus propios archivos en lugar del dispositivo de bloque. Estoy seguro de que tiene razón al decir que ext2 hace esto. ext3/ext4 con su sistema de diario no lo hace. Está menos claro cuáles fueron los problemas que llevaron a este diseño. Las personas a las que despotricaba se cansaron de dar explicaciones.
ext4_readdir() no se ha cambiado para satisfacer la diatriba de Linus. Tampoco veo que se use su enfoque deseado en readdir() de otros sistemas de archivos. Creo que XFS también usa el caché de búfer para directorios. bcachefs no usa el caché de la página para readdir() en absoluto; utiliza su propio caché para btrees. No estoy seguro acerca de btrfs.
4. ¿Por qué podríamos esperar Buffers
en particular para ser más grande o más pequeño?
En este caso resulta que el tamaño del diario ext4 para mi sistema de archivos es 128M. Entonces esto explica por qué 1) mi caché de búfer puede estabilizarse en un poco más de 128M; 2) la memoria caché del búfer no escala proporcionalmente con la mayor cantidad de RAM en mi computadora portátil.
Para conocer otras causas posibles, consulte ¿Qué es la columna de búferes en la salida de forma gratuita? Tenga en cuenta que los "búferes" informados por free
es en realidad una combinación de Buffers
y memoria de bloque de núcleo recuperable.
Para verificar que las escrituras de diarios usan la memoria caché del búfer, simulé un sistema de archivos en una memoria RAM rápida y agradable (tmpfs) y comparé el uso máximo del búfer para diferentes tamaños de diarios.
# 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
Historia de esta respuesta:Cómo llegué a mirar el diario
Encontré primero el correo electrónico de Ted Tso y me intrigó que enfatizara escribir almacenamiento en caché Me sorprendería si "sucio", no escrito los datos pudieron alcanzar el 30% de la RAM en mi sistema. sudo atop
muestra que durante un intervalo de 10 segundos, el sistema en cuestión escribe constantemente solo 1 MB. El sistema de archivos en cuestión podría mantenerse al día con más de 100 veces esta velocidad. (Está en una unidad de disco duro USB2, rendimiento máximo ~20 MB/s).
Usando blktrace (btrace -w 10 /dev/sda
) confirma que las E/S que se almacenan en caché deben ser escrituras, porque casi no se leen datos. También que mysqld
es el único espacio de usuario proceso haciendo IO.
Detuve el servicio responsable de las escrituras (icinga2 escribiendo en mysql) y volví a verificar. Vi que los "amortiguadores" cayeron a menos de 20 millones, no tengo explicación para eso, y me quedé allí. Reiniciar el escritor nuevamente muestra que los "búferes" aumentan ~0.1M por cada intervalo de 10 segundos. Observé que mantiene esta tasa constantemente, volviendo a subir a 70M y más.
Ejecutando echo 3 | sudo tee /proc/sys/vm/drop_caches
fue suficiente para bajar los "amortiguadores" nuevamente, a 4.5M. Esto prueba que mi acumulación de búferes es un caché "limpio", que Linux puede eliminar inmediatamente cuando sea necesario. Este sistema no está acumulando no escrito datos. (drop_caches
no realiza ninguna reescritura y, por lo tanto, no puede descartar páginas sucias. Si quisiera ejecutar una prueba que limpiara el caché primero, usaría el sync
comando).
Todo el directorio mysql tiene solo 150M. Los búferes de acumulación deben representar bloques de metadatos de escrituras mysql, pero me sorprendió pensar que habría tantos bloques de metadatos para estos datos.
Tu versión de free
tiene la idea correcta. De forma predeterminada, combina búferes y caché en su informe. Esto se debe a que básicamente son lo mismo. Ambos son la computadora recordando en RAM (Más rápido que almacenamiento secundario:Discos y SSD), lo que ya ha visto al leer Disco y SSD.
Si el sistema operativo siente que la memoria es mejor utilizada por otra cosa, entonces puede liberarla. Por lo tanto, no se preocupe por el búfer y el caché.
Sin embargo, mirar un DVD puede hacer que el búfer aumente y desaloje otro contenido del búfer/caché. Por lo tanto, puede usar nocache para ejecutar el reproductor de DVD (si está causando un problema ).