El 30% de la RAM son "buffers". ¿Qué es?


12
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           501M        146M         19M        9.7M        335M        331M
Swap:          1.0G         85M        938M

$ free -w -h
              total        used        free      shared     buffers       cache   available
Mem:           501M        146M         19M        9.7M        155M        180M        331M
Swap:          1.0G         85M        938M

¿Cómo puedo describir o explicar "buffers" en la salida de free?

No tengo ningún problema (conocido) con este sistema. Solo estoy sorprendido y curioso de ver que "buffers" es casi tan alto como "cache" (155M vs 180M). Pensé que "caché" representaba el caché de página del contenido del archivo, y tiende a ser la parte más importante de "caché / buffers". Estoy menos claro para qué sirven los "amortiguadores".

Por ejemplo, comparé esto con mi computadora portátil, que tiene más RAM. En mi computadora portátil, la cifra de "buffers" es un orden de magnitud menor que "cache" (200M vs 4G). Si tuviera una comprensión adecuada de lo que eran los "buffers", entonces podría comenzar a preguntar por qué los buffers podrían crecer a una proporción tan grande en el sistema más pequeño.

man proc (Ignoro la definición hilarantemente desactualizada de "grande"):

Tampones% lu

Almacenamiento relativamente temporal para bloques de disco sin procesar que no deberían ser tremendamente grandes (20 MB más o menos).

% Lu almacenado en caché

Caché en memoria para archivos leídos del disco (el caché de página). No incluye SwapCached.


$ free -V
free from procps-ng 3.3.12
$ uname -r
4.9.0-6-marvell
$ systemd-detect-virt
none

$ cat /proc/meminfo
MemTotal:         513976 kB
MemFree:           20100 kB
MemAvailable:     339304 kB
Buffers:          159220 kB
Cached:           155536 kB
SwapCached:         2420 kB
Active:           215044 kB
Inactive:         216760 kB
Active(anon):      56556 kB
Inactive(anon):    73280 kB
Active(file):     158488 kB
Inactive(file):   143480 kB
Unevictable:       10760 kB
Mlocked:           10760 kB
HighTotal:             0 kB
HighFree:              0 kB
LowTotal:         513976 kB
LowFree:           20100 kB
SwapTotal:       1048572 kB
SwapFree:         960532 kB
Dirty:               240 kB
Writeback:             0 kB
AnonPages:        126912 kB
Mapped:            40312 kB
Shmem:              9916 kB
Slab:              37580 kB
SReclaimable:      29036 kB
SUnreclaim:         8544 kB
KernelStack:        1472 kB
PageTables:         3108 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1305560 kB
Committed_AS:    1155244 kB
VmallocTotal:     507904 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

$ sudo slabtop --once
 Active / Total Objects (% used)    : 186139 / 212611 (87.5%)
 Active / Total Slabs (% used)      : 9115 / 9115 (100.0%)
 Active / Total Caches (% used)     : 66 / 92 (71.7%)
 Active / Total Size (% used)       : 31838.34K / 35031.49K (90.9%)
 Minimum / Average / Maximum Object : 0.02K / 0.16K / 4096.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 59968  57222   0%    0.06K    937       64      3748K buffer_head            
 29010  21923   0%    0.13K    967       30      3868K dentry                 
 24306  23842   0%    0.58K   4051        6     16204K ext4_inode_cache       
 22072  20576   0%    0.03K    178      124       712K kmalloc-32             
 10290   9756   0%    0.09K    245       42       980K kmalloc-96             
  9152   4582   0%    0.06K    143       64       572K kmalloc-node           
  9027   8914   0%    0.08K    177       51       708K kernfs_node_cache      
  7007   3830   0%    0.30K    539       13      2156K radix_tree_node        
  5952   4466   0%    0.03K     48      124       192K jbd2_revoke_record_s   
  5889   5870   0%    0.30K    453       13      1812K inode_cache            
  5705   4479   0%    0.02K     35      163       140K file_lock_ctx          
  3844   3464   0%    0.03K     31      124       124K anon_vma               
  3280   3032   0%    0.25K    205       16       820K kmalloc-256            
  2730   2720   0%    0.10K     70       39       280K btrfs_trans_handle     
  2025   1749   0%    0.16K     81       25       324K filp                   
  1952   1844   0%    0.12K     61       32       244K kmalloc-128            
  1826    532   0%    0.05K     22       83        88K trace_event_file       
  1392   1384   0%    0.33K    116       12       464K proc_inode_cache       
  1067   1050   0%    0.34K     97       11       388K shmem_inode_cache      
   987    768   0%    0.19K     47       21       188K kmalloc-192            
   848    757   0%    0.50K    106        8       424K kmalloc-512            
   450    448   0%    0.38K     45       10       180K ubifs_inode_slab       
   297    200   0%    0.04K      3       99        12K eventpoll_pwq          
   288    288 100%    1.00K     72        4       288K kmalloc-1024           
   288    288 100%    0.22K     16       18        64K mnt_cache              
   287    283   0%    1.05K     41        7       328K idr_layer_cache        
   240      8   0%    0.02K      1      240         4K fscrypt_info           

Respuestas:


13
  1. ¿Cuál es la diferencia entre "buffer" y el otro caché?
  2. ¿Por qué vemos esta distinción tan prominentemente? (Posible razón histórica)
  3. ¿Para qué se Buffersusan?
  4. ¿Por qué podríamos esperar Buffersen particular que sea más grande o más pequeño?

1. ¿Cuál es la diferencia entre "buffer" y el otro tipo de caché?

Buffersinforma la cantidad de caché de página utilizada para dispositivos de bloque. 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é vemos esta distinción tan prominentemente? (Posible razón histórica)

El caché de la página funciona en unidades del tamaño de página de MMU, generalmente un mínimo de 4096 bytes. Esto es esencial para mmap(), es decir, el acceso a archivos mapeados en memoria. [1] [2] Se utiliza para compartir páginas de código de programa / biblioteca cargado entre procesos independientes y permite cargar páginas individuales bajo demanda. (También para descargar páginas cuando algo más necesita espacio, y no se han utilizado recientemente).

[1] E / S mapeadas en memoria: el manual de la Biblioteca GNU C.
[2] mmap- Wikipedia.

Los primeros UNIX tenían una "memoria caché de búfer" de bloques de disco y no tenían mmap (). Aparentemente, cuando se agregó mmap () por primera vez, simplemente atornillaron la caché de la página en la parte superior de la caché del búfer. Esto es tan desordenado como parece. Finalmente, los sistemas operativos basados ​​en UNIX se deshicieron de la memoria caché del búfer. 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 llamaba "caché de búfer unificado", quizás porque la gente estaba más familiarizada con el "caché de búfer". [3]

[3] UBC: un subsistema de E / S unificado eficiente y memoria caché para NetBSD

"Un giro interesante que Linux agrega 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_headestructuras. Cuando una página modificada se va a volver a escribir en el disco, la E / S las solicitudes 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 usado para escrituras, pero no para lecturas. "La memoria caché de la página utilizó la memoria caché del búfer para volver a escribir sus datos, necesitando una copia extra de los datos y duplicando los requisitos de memoria para algunas cargas de escritura" (?). [4] No nos preocupemos demasiado por los detalles, pero esta historia sería una de las razones por las que Linux informa el Buffersuso 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 un disco IO directamente hacia y desde la página de caché de página". [4] Linux 2.4 fue lanzado en 2001.

3. ¿Para qué se Buffersusan?

Los dispositivos de bloque se tratan como archivos, y también la memoria caché de la 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 del archivo a través de él, por lo que no hay "doble almacenamiento en caché".

Pienso en la Buffersparte de la memoria caché de la página como la memoria caché del búfer de Linux. Aunque algunas fuentes pueden estar en desacuerdo con esta terminología.

La cantidad de caché de búfer que utiliza el sistema de archivos, si corresponde, depende de los detalles del sistema de archivos específico. El sistema en la pregunta usa ext4. ext3 / ext4 usa la memoria 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 la memoria caché del 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 páginas separadas y cachés de búfer. Desde 2.4, la página y el caché del búfer están unificados y Buffersson bloques de disco sin procesar no representados en el caché de la página, es decir, no son datos de archivo.

...

Sin embargo, la memoria caché del búfer permanece, ya que el núcleo aún necesita realizar bloque de E / S en términos de bloques, no de páginas. Como la mayoría de los bloques representan datos de archivo, 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 procesar, por ejemplo) y, por lo tanto, solo está representada por el caché del búfer.

- Un par de respuestas de Quora por Robert Love , última actualización de 2013.

Ambos escritores son desarrolladores de Linux que han trabajado con la gestión de memoria del kernel de Linux. La primera fuente es más específica sobre detalles técnicos. La segunda fuente es un resumen más general, que puede ser contradicho y desactualizado en algunos detalles.

Es cierto que los sistemas de archivos pueden realizar escrituras de metadatos de páginas parciales, aunque el caché esté indexado en páginas. Incluso los procesos de los usuarios pueden realizar escrituras de páginas parciales cuando usan write()(en lugar de mmap()), al menos directamente en un dispositivo de bloque. Esto solo se aplica a escrituras, no a lecturas. Cuando lee la memoria caché de la página, la memoria caché de la página siempre lee páginas completas.

A Linus le gustaba decir 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 escribir metadatos de página parcial incluso con la 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. No está tan claro cuáles fueron los problemas que llevaron a este diseño. La gente con la que estaba despotricando se cansó de explicar.

ext4_readdir () no se ha cambiado para satisfacer la diatriba de Linus. Tampoco veo su enfoque deseado utilizado en readdir () de otros sistemas de archivos. Creo que XFS también usa la memoria caché del búfer para los directorios. bcachefs no utiliza la memoria caché de la página para readdir () en absoluto; utiliza su propio caché para btrees. Puede que me falte algo en btrfs.

4. ¿Por qué podríamos esperar Buffersen particular que sea más grande o más pequeño?

En este caso, el tamaño del diario ext4 para mi sistema de archivos es de 128M. Esto explica por qué 1) mi caché de búfer puede estabilizarse a 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 ¿Cuál es la columna de búferes en la salida de libre? Tenga en cuenta que los "buffers" informados por freees en realidad una combinación de Buffersmemoria de losa recuperable.


Para verificar que las escrituras del diario usan la memoria caché del búfer, simulé un sistema de archivos en una RAM rápida y agradable (tmpfs), y comparé el uso máximo del búfer para diferentes tamaños de 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

Historia de esta respuesta: cómo llegué a mirar el diario

Primero encontré el correo electrónico de Ted Tso, y me intrigó que enfatizara el almacenamiento en caché de escritura . Me sorprendería si los datos "sucios" y no escritos pudieran alcanzar el 30% de RAM en mi sistema. sudo atopmuestra que en un intervalo de 10 segundos, el sistema en cuestión escribe de manera consistente 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).

El uso de blktrace ( btrace -w 10 /dev/sda) confirma que las E / S que se almacenan en caché deben escribirse, porque casi no se leen datos. Además, ese mysqldes el único proceso de espacio de usuario que realiza IO.

Detuve el servicio responsable de las escrituras (icinga2 escribiendo en mysql) y volví a verificar. Vi "amortiguadores" bajar a menos de 20 millones, no tengo explicación para eso, y quedarme allí. Reiniciar el escritor nuevamente muestra que los "buffers" aumentan en ~ 0.1M por cada intervalo de 10 segundos. Observé que mantiene esta tasa de forma constante, subiendo de nuevo a 70M y más.

Correr echo 3 | sudo tee /proc/sys/vm/drop_cachesfue suficiente para bajar "buffers" nuevamente, a 4.5M. Esto demuestra que mi acumulación de búferes es un caché "limpio", que Linux puede eliminar de inmediato cuando sea necesario. Este sistema no está acumulando datos no escritos . ( drop_cachesno realiza ninguna reescritura y, por lo tanto, no puede soltar páginas sucias. Si desea ejecutar una prueba que limpió primero el caché, usaría el synccomando).

Todo el directorio mysql es solo 150M. Los búferes acumulados deben representar bloques de metadatos de las escrituras de mysql, pero me sorprendió pensar que habría tantos bloques de metadatos para estos datos.


3

Su versión de freetiene la idea correcta. Por defecto, combina buffers y caché en su informe. Esto se debe a que son básicamente lo mismo. Ambos son la computadora que recuerda en RAM (más rápido que el almacenamiento secundario: discos y SSD), lo que ya ha visto al leer Disco y SSD.

Si el sistema operativo considera 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 suba y desalojar otro contenido de búfer / caché. Por lo tanto, puede usar nocache para ejecutar el reproductor de DVD ( si está causando un problema ).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.