GNU/Linux >> Tutoriales Linux >  >> Linux

Linux:¿por qué se informaron problemas de "bloqueo de memoria USB" en 2013? ¿Por qué no se resolvió este problema con el código existente de "no-i/o Dirty Throttling"?

El pernicioso problema de bloqueo de la memoria USB:LWN.net, noviembre de 2013.

Artem S. Tashkinov encontró recientemente un problema que será familiar para al menos algunos lectores de LWN. Conecte un dispositivo de almacenamiento lento (una memoria USB, por ejemplo, o un reproductor multimedia) en una máquina Linux y escriba una gran cantidad de datos en él. Todo el sistema procede a colgarse , posiblemente durante minutos.

Esta vez, sin embargo, Artem hizo una observación interesante:el sistema se detenía cuando se ejecutaba con un kernel de 64 bits, pero no se experimentaba ese problema cuando se usaba un kernel de 32 bits en el mismo hardware.

El artículo explica que con un kernel de 64 bits, la memoria caché de página sucia (caché de reescritura) podía crecer hasta el 20 % de la memoria de forma predeterminada. Con un kernel de 32 bits, se limitó efectivamente a ~180 MB.

Linus sugirió limitarlo a ~180 MB en 64 bits también, sin embargo, el Linux actual (v4.18) no hace esto. Compare el parche sugerido por Linus con la función actual en Linux 4.18. El mayor argumento en contra de tales cambios provino de Dave Chinner. Señaló que reducir demasiado el almacenamiento en búfer haría que los sistemas de archivos sufrieran fragmentación. También explicó que "para transmitir IO normalmente necesitamos al menos
5 segundos de datos sucios almacenados en caché datos para compensar los retrasos.”

Estoy confundido. ¿Por qué el bloqueo de la memoria USB hizo que todo el sistema se colgara?

Estoy confundido porque leí un artículo anterior que describe el código fusionado en 2011 (Linux 3.2). Muestra que el núcleo debería haber estado controlando la caché de páginas sucias por dispositivo:

Aceleración sucia sin E/S:LWN.net, 2011

Ahí es donde entra en juego el conjunto de parches de Fengguang. Él está intentando crear un ciclo de control capaz de determinar cuántas páginas se debe permitir que cada proceso ensucie en un momento dado. Los procesos que exceden su límite simplemente se suspenden por un tiempo para permitir que el sistema de reescritura los alcance.

[…]

El objetivo del sistema es mantener el número de páginas sucias en el punto establecido; si las cosas se salen de la línea, se aplicará una cantidad cada vez mayor de fuerza para que las cosas vuelvan a estar donde deberían estar.

[…]

Sin embargo, esta relación no se puede calcular realmente sin tener en cuenta el dispositivo de respaldo (BDI). Un proceso puede estar ensuciando páginas almacenadas en un BDI determinado, y el sistema puede tener un exceso de páginas sucias en este momento, pero la sabiduría de limitar ese proceso depende también de cuántas páginas sucias existen para ese BDI. […] Un BDI con pocas páginas sucias puede eliminar su acumulación rápidamente, por lo que probablemente pueda permitirse tener algunas más, incluso si el sistema está algo más sucio de lo que a uno le gustaría. Por lo tanto, el conjunto de parches modifica el pos_ratio calculado para un BDI específico utilizando una fórmula complicada que analiza qué tan lejos está ese BDI específico de su propio punto de ajuste y su ancho de banda observado. El resultado final es un pos_ratio modificado que describe si el sistema debería ensuciar más o menos páginas respaldadas por el BDI dado y en qué medida.

El control por dispositivo se agregó incluso antes que esto:Smarter write throttling, 2007 LWN.net. [PARCHE 0/23] por dispositivo regulación sucia -v10. Se fusionó en la versión 2.6.24 de Linux.

Respuesta aceptada:

  1. El artículo de 2013 está mal
  2. ¿Un error en LWN? ¿Estás seguro?
  3. Colas largas en dispositivos de E/S, creadas por reescritura "en segundo plano"
  4. ¿Limitaciones de la "regulación sucia sin E/S"?
  5. Informes originales de problemas de "bloqueo de memoria USB"
  6. El límite sucio se calculó incorrectamente [2014]
  7. Bloqueo de asignaciones de páginas enormes en IO [2011]
  8. ¿"Páginas sucias llegando al final de la LRU"? [antes de 2013]

1. El artículo de 2013 está mal

El artículo "Puerta de la memoria USB" le da una impresión muy engañosa. Tergiversa tanto el informe original como la serie de respuestas.

Artem no informó que todo el sistema se bloqueó cuando vació las escrituras almacenadas en caché en una memoria USB. Su informe original solo se quejaba de que ejecutar el comando "sincronizar" podía llevar hasta "docenas de minutos". Esta distinción se hace explícita en una respuesta de Linus Torvalds:

En realidad, es muy fácil de reproducir simplemente tomando su llave USB promedio y tratando de escribir en ella. Acabo de hacerlo con una imagen ISO
aleatoria y es doloroso. Y no es que sea doloroso hacer
la mayoría de las otras cosas en segundo plano, pero si por casualidad ejecuta
cualquier cosa que se "sincronice" (y sucede en scripts), la cosa simplemente
se detiene bruscamente.
Por minutos.

2. ¿Un error en LWN? ¿Estás seguro?

Jon Corbet tenía quince años de experiencia, informando semanalmente sobre el desarrollo del kernel de Linux. Esperaba que el artículo fuera al menos cerrado para hacerlo bien, en algún sentido. Así que quiero procesar los dos registros diferentes y buscar puntos detallados en los que estén de acuerdo o en desacuerdo.

Leí toda la discusión original, usando los archivos en lore.kernel.org. Creo que los mensajes son bastante claros.

Estoy 100% seguro de que el artículo malinterpreta la discusión. En los comentarios debajo del artículo, al menos dos lectores repitieron la afirmación falsa con sus propias palabras y nadie los corrigió. El artículo continúa esta confusión en el tercer párrafo:

Todos esos datos obstruyen las colas de E/S, posiblemente retrasando otras operaciones. Y, tan pronto como alguien llame a sync(), las cosas se detendrán hasta que se escriba toda la cola.

Esto podría ser una confusión de Linus diciendo "la cosa simplemente se detiene". “La cosa” se refiere a “cualquier cosa que haga sync “. Pero Corbet escribe como si “la cosa” significara “todo el sistema”.

Según Linus, este es un problema del mundo real. Pero la gran mayoría de las "cosas" no llame a la operación de sincronización() de todo el sistema.[1]

¿Por qué podría Corbet confundir esto con “todo el sistema”? Supongo que ha habido una serie de problemas, y después de un tiempo se vuelve difícil mantenerlos separados en tu cabeza :-). Y aunque LWN ha descrito el desarrollo de la regulación sucia por dispositivo (y por proceso), en general, supongo que no hay mucho escrito sobre estos detalles. Muchos documentos solo describen la configuración global del límite sucio.

3. Largas colas en dispositivos de E/S, creadas por reescritura "en segundo plano"

Artem publicó un segundo informe en el hilo, donde "el servidor casi se detiene y otras solicitudes de IO tardan mucho más en completarse".

Relacionado:Linux – ¿Enrutamiento a través de iptables?

Este segundo informe no coincide con las afirmaciones sobre el bloqueo de una memoria USB. Sucedió después de crear un archivo de 10 GB en un interno disco. Este es un problema diferente.

El informe no confirmó si esto podría mejorarse cambiando los límites sucios. Y hay un análisis más reciente de casos como este. Hay un problema importante cuando obstruye la cola de E/S de su disco principal. Puede sufrir largas demoras en un disco en el que confía constantemente, para cargar el código del programa a pedido, guardar documentos y datos de aplicaciones usando write() + fsync(), etc.

Hacia una reescritura en segundo plano menos molesta:LWN.net, 2016

Cuando el código de administración de memoria decide escribir un rango de datos sucios, el resultado es una solicitud de E/S enviada al subsistema de bloques. Esa solicitud puede pasar algún tiempo en el programador de E/S, pero finalmente se envía al controlador del dispositivo de destino.

El problema es que, si hay muchos datos sucios para escribir, puede terminar habiendo un gran número (como miles) de solicitudes en cola para el dispositivo. Incluso una unidad razonablemente rápida puede tardar algún tiempo en procesar tantas solicitudes. Si alguna otra actividad (hacer clic en un enlace en un navegador web, por ejemplo, o iniciar una aplicación) genera solicitudes de E/S en el mismo dispositivo de bloque, esas solicitudes van al final de esa larga cola y es posible que no se atiendan durante algún tiempo. Si se generan varias solicitudes sincrónicas (fallos de página de una aplicación recién iniciada, por ejemplo), es posible que cada una de esas solicitudes, a su vez, tenga que pasar por esta larga cola. Ese es el punto donde las cosas parecen detenerse.

[…]

La mayoría de los controladores de bloques también mantienen sus propias colas internamente. Esas colas de nivel inferior pueden ser especialmente problemáticas ya que, cuando llega una solicitud, ya no está sujeta al control del programador de E/S (si es que existe un programador de E/S).

Los parches se fusionaron para mejorar esto a finales de 2016 (Linux 4.10). Este código se conoce como "limitación de reescritura" o WBT. Buscando en la web wbt_lat_usec también encuentra algunas historias más sobre esto. (El documento inicial escribe sobre wb_lat_usec , pero está desactualizado). Tenga en cuenta que la limitación de reescritura no funciona con los programadores de E/S CFQ o BFQ. CFQ ha sido popular como programador de E/S predeterminado, incluso en compilaciones de kernel predeterminadas hasta Linux v4.20. CFQ se elimina en el kernel v5.0.

Hubo pruebas para ilustrar el problema (y la solución prototipo) tanto en un SSD (que parecía NVMe) como en un "disco duro normal". El disco duro "no era tan malo como los dispositivos de mayor profundidad de cola, en los que tenemos E/S con ráfagas enormes".

No estoy seguro acerca de los "miles" de solicitudes en cola, pero al menos hay dispositivos NVMe que pueden poner en cola cientos de solicitudes. La mayoría de los discos duros SATA permiten poner en cola 32 solicitudes ("NCQ"). Por supuesto, el disco duro tardaría más en completar cada solicitud.

4. ¿Limitaciones de la "regulación sucia sin E/S"?

La "regulación sucia sin E/S" es un sistema de ingeniería bastante complejo. También ha sido modificado con el tiempo. Estoy seguro de que hubo, y todavía hay, algunos limitaciones dentro de este código.

El informe de LWN, los comentarios del código/parche y las diapositivas de la presentación detallada muestran que se han considerado una gran cantidad de escenarios. Esto incluye la notoria memoria USB lenta v.s. accionamiento principal rápido. Los casos de prueba incluyen la frase "1000 dd's concurrentes" (es decir, escritores secuenciales).

Hasta el momento, no sé cómo demostrar y reproducir ninguna limitación dentro del código de regulación sucio.

He visto varias descripciones de soluciones de problemas que estaban fuera del código de regulación sucio. La solución más reciente que encontré fue en 2014; consulte las secciones siguientes. En el hilo sobre el que informa LWN, aprendemos:

En las últimas versiones, problemas como este fueron
causados ​​por problemas en la recuperación que se cansaron al ver muchas páginas sucias
/ under writeback y terminaron atascados esperando que IO terminara.

[…] El script systemtap detectó ese tipo de áreas y
creo que están reparadas.

Mel Gorman también dijo que había algunos "problemas pendientes".

Aunque todavía hay problemas. Si todas las páginas sucias estuvieran respaldadas por un dispositivo lento, entonces la limitación sucia eventualmente causará estancamientos en el balanceo de páginas sucias […]

Este pasaje fue lo único que pude encontrar en el hilo de discusión informado, que se acerca a respaldar la interpretación de LWN. Ojalá entendiera a qué se refería :-(. O cómo demostrarlo y por qué no pareció surgir como un problema significativo en las pruebas que realizaron Artem y Linus.

5. Informes genuinos de problemas de "bloqueo de memoria USB"

Aunque ni Artem ni Linux informaron de un "bloqueo de la memoria USB" que afectó a todo el sistema, podemos encontrar varios informes de esto en otros lugares. Esto incluye informes de los últimos años, mucho después de la última corrección conocida.

No sé cuál es la diferencia. Tal vez sus condiciones de prueba fueron diferentes de alguna manera, o tal vez se crearon algunos problemas nuevos en el núcleo desde 2013...

  • https://utcc.utoronto.ca/~cks/space/blog/linux/USBDrivesKillMyPerformance / https://utcc.utoronto.ca/~cks/space/blog/linux/FixingUSBDriveResponsiveness [2017]
  • ¿Por qué mi PC se congela mientras copio un archivo a un pendrive? [enero de 2014]
  • El sistema se retrasa al realizar grandes operaciones de lectura y escritura en discos externos [2018]
  • La interfaz gráfica de usuario de Linux deja de responder cuando se realiza una E/S de disco pesada:¿qué ajustar? [2019]

6. El límite sucio se calculó incorrectamente [2014]

Hubo una corrección interesante en enero de 2014 (aplicada en el kernel v3.14). En la pregunta, dijimos que el límite predeterminado se estableció en el 20 % de la memoria. En realidad, está configurado en un 20 % de la memoria que está disponible para la caché de páginas sucias. Por ejemplo, los búferes del kernel enviaron datos para los sockets de red TCP/IP. Los búferes de socket no se pueden eliminar y reemplazar con caché de página sucia :-).

El problema era que el núcleo contaba con la memoria intercambiable, como si pudiera intercambiar datos a favor de la caché de páginas sucias. Aunque esto es posible en teoría, el kernel está fuertemente sesgado para evitar el intercambio y prefiere eliminar el caché de la página. Este problema se ilustró con, adivina qué, una prueba que involucró escribir en una memoria USB lenta y notar que causaba bloqueos en todo el sistema :-).

Relacionado:Linux:¿por qué redirigir la salida a 2>&1 y 1>&2?

Ver Re:[parche 0/2] mm:reducir las paradas de recuperación con anon pesado y caché sucio

La solución es que dirty_ratio ahora se trata solo como una proporción de la caché de archivos.

Según el desarrollador del kernel que sufrió el problema, "las condiciones de activación parecen bastante plausibles:alto uso de memoria anon con E/S con mucho búfer y configuración de intercambio, y es muy probable que esto esté sucediendo en la naturaleza". Así que esto podría explicar algunos informes de usuarios alrededor de 2013 o antes.

7. Bloqueo de asignaciones de páginas enormes en IO [2011]

Este fue otro problema:páginas enormes, unidades lentas y largas demoras (LWN.net, noviembre de 2011). Este problema con las páginas grandes ahora debería solucionarse.

Además, a pesar de lo que dice el artículo, creo que la mayoría de las PC con Linux actuales realmente no usan páginas grandes. Esto podría estar cambiando a partir de Debian 10. Sin embargo, incluso cuando Debian 10 comienza a asignar páginas enormes donde sea posible, me parece claro que no impondrá ningún retraso, a menos que cambie otra configuración llamada defrag a "siempre".

8. “Páginas sucias llegando al final de la LRU” [antes de 2013]

No he investigado esto, pero me pareció interesante:

mgorman 2011:Este es un nuevo tipo de bloqueo relacionado con USB porque se debe a la escritura de compactación síncrona donde, como en el pasado, el gran problema era que las páginas sucias
llegaban al final de la LRU y se escribían con recuperación .

mgorman 2013:El trabajo en esa área general abordó
problemas tales como páginas sucias que llegaban al final de la LRU (uso excesivo de CPU
)

Si estos son dos problemas diferentes de "llegar al final de la LRU", entonces el primero parece que podría ser muy malo. Parece que cuando una página sucia se convierte en la página utilizada menos recientemente, cualquier intento de asignar memoria se retrasaría, hasta que esa página sucia terminara de escribirse.

Sea lo que sea que signifique, dice que el problema ya está solucionado.

[1] Una excepción:por un tiempo, el administrador de paquetes de Debian dpkg usó sync() para mejorar el rendimiento. Esto se eliminó debido al problema exacto de que sync() podría tomar mucho tiempo. Cambiaron a un enfoque usando sync_file_range() en Linux. Consulte el error de Ubuntu n.º 624877, comentario 62.

Parte de un intento anterior de responder esta pregunta; en su mayoría, esto debería ser redundante:

Creo que podemos explicar los dos informes de Artem como consistentes con el código de "Aceleración sucia sin E/S".

El código de limitación sucia tiene como objetivo permitir que cada dispositivo de respaldo tenga una parte justa del "caché de reescritura total", "que se relaciona con su velocidad de escritura promedio actual en relación con los otros dispositivos". Esta redacción es de la documentación de /sys/class/bdi/.[2]

En el caso más simple, solo se escribe en un dispositivo de respaldo. En ese caso, la parte justa del dispositivo es del 100%. Las llamadas a write() se aceleran para controlar la memoria caché de reescritura general y mantenerla en un "punto de ajuste".

Las escrituras comienzan a limitarse a mitad de camino entre dirty_background_ratio – el punto que inicia la escritura en segundo plano – y dirty_ratio – el límite estricto en la memoria caché de reescritura. De forma predeterminada, estos son el 10 % y el 20 % de la memoria disponible.

Por ejemplo, aún podría llenar hasta un 15% escribiendo solo en su disco principal. Podría tener gigabytes de escrituras en caché, según la cantidad de RAM que tenga. En ese momento, las llamadas de escritura () comenzarán a acelerarse para que coincidan con la velocidad de escritura diferida, pero eso no es un problema. Espero que los problemas de bloqueo sean para las llamadas read() y fsync(), que se atascan detrás de grandes cantidades de IO no relacionadas. Este es el problema específico que aborda el código de "limitación de reescritura". Algunos de los envíos de parches de WBT incluyen descripciones de problemas, que muestran los terribles retrasos que esto causa.

Del mismo modo, puede llenar el 15% por completo con escrituras en una memoria USB. Se reducirán las escrituras adicionales en el USB. Pero el disco principal no usaría nada de lo que le corresponde. Si comienza a llamar a write() en su sistema de archivos principal, entonces no se limitará, o al menos se retrasará mucho menos. Y creo que las escrituras USB se acelerarían aún más para equilibrar las dos escritoras.

Espero que la memoria caché de reescritura general pueda elevarse temporalmente por encima del punto de ajuste. En algunos casos más exigentes, puede alcanzar el límite estricto en la memoria caché de reescritura general. El límite estricto predeterminado es el 20 % de la memoria disponible; la opción de configuración es dirty_ratio / dirty_bytes . Tal vez pueda hacer clic en esto porque un dispositivo puede ralentizarse (quizás debido a un patrón de E/S más aleatorio) y la limitación sucia no reconoce el cambio de velocidad inmediatamente.

[2] Puede notar que este documento sugiere que puede manualmente limitar la proporción de caché de reescritura que se puede usar para una partición/sistema de archivos específico. La configuración se llama /sys/class/bdi/*/max_ratio . Tenga en cuenta que "si el dispositivo que desea limitar es el único en el que está escrito actualmente, la limitación no tiene un gran efecto".


Linux
  1. ¿Cuál es el nivel de ejecución actual del sistema Linux?

  2. Linux:¿por qué no hay un sistema de archivos Rootfs presente en el sistema?

  3. Linux:¿por qué las utilidades de Linux no utilizan una llamada al sistema para obtener la hora actual?

  4. Comprobar la carga del sistema en Linux

  5. ¿El problema del rebaño atronador existe más en Linux?

Introducción al sistema de archivos de Linux

Gestión de intercambio en el sistema Linux moderno

Cómo cambiar la identidad de un sistema Linux

Los efectos de agregar usuarios a un sistema Linux

Cómo cambiar el shell predeterminado en el sistema Linux

Cómo usar el comando fd en el sistema Linux