GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo limitan las canalizaciones el uso de memoria?

Brian Kernighan explica en este video la atracción inicial de Bell Labs por los lenguajes/programas pequeños basados ​​en limitaciones de memoria

Una máquina grande sería de 64 kbytes, K, no M o G, y eso significaba que ningún programa individual podía ser muy grande, por lo que había una tendencia natural a escribir programas pequeños, y luego el mecanismo de canalización, básicamente redirección de salida, hizo posible vincular un programa a otro.

Pero no entiendo cómo esto podría limitar el uso de la memoria teniendo en cuenta el hecho de que los datos deben almacenarse en la RAM para transmitirse entre programas.

De Wikipedia:

En la mayoría de los sistemas similares a Unix, todos los procesos de una canalización se inician al mismo tiempo [énfasis mío] , con sus flujos correctamente conectados y administrados por el programador junto con todos los demás procesos que se ejecutan en la máquina. Un aspecto importante de esto, que distingue a las tuberías de Unix de otras implementaciones de tuberías, es el concepto de almacenamiento en búfer:por ejemplo, un programa de envío puede producir 5000 bytes por segundo, y un programa de recepción solo puede aceptar 100 bytes por segundo, pero no los datos se pierden. En su lugar, la salida del programa de envío se mantiene en el búfer. Cuando el programa receptor está listo para leer datos, el siguiente programa en la canalización lee del búfer. En Linux, el tamaño del búfer es de 65536 bytes (64 KB). Un filtro de terceros de código abierto llamado bfr está disponible para proporcionar búferes más grandes si es necesario.

Esto me confunde aún más, ya que anula por completo el propósito de los programas pequeños (aunque serían modulares hasta cierta escala).

Lo único que puedo pensar como una solución a mi primera pregunta (las limitaciones de memoria son problemáticas dependiendo del tamaño de los datos) sería que los grandes conjuntos de datos simplemente no se calculaban en ese entonces y el problema real que las canalizaciones debían resolver era el cantidad de memoria requerida por los propios programas. Pero dado el texto en negrita en la cita de Wikipedia, incluso esto me confunde:ya que no se implementa un programa a la vez.

Todo esto tendría mucho sentido si se usaran archivos temporales, pero tengo entendido que las canalizaciones no escriben en el disco (a menos que se use el intercambio).

Ejemplo:

sed 'simplesubstitution' file | sort | uniq > file2

Me queda claro que sed está leyendo el archivo y escupiéndolo línea por línea. Pero sort , como dice BK en el video vinculado, es un punto final, por lo que todos los datos deben leerse en la memoria (¿o no?), luego se pasan a uniq , que (en mi opinión) sería un programa de una línea a la vez. Pero entre la primera y la segunda tubería, todos los datos deben estar en la memoria, ¿no?

Relacionado:Ubuntu:¿ejecutar un comando cuando se inserta un CD/DVD/BD?

Respuesta aceptada:

Los datos no necesitan ser almacenados en RAM. Las tuberías bloquean a sus escritores si los lectores no están allí o no pueden seguir el ritmo; bajo Linux (y la mayoría de las otras implementaciones, me imagino) hay algo de almacenamiento en búfer, pero eso no es necesario. Como mencionaron mtraceur y JdeBP (consulte la respuesta de este último), las primeras versiones de Unix almacenaban tuberías en el disco, y así es como ayudaron a limitar el uso de la memoria:una tubería de procesamiento podría dividirse en pequeños programas, cada uno de los cuales procesaría algunos datos , dentro de los límites de los búferes del disco. Los programas pequeños requieren menos memoria, y el uso de tuberías significaba que el procesamiento podía serializarse:el primer programa se ejecutaba, llenaba su búfer de salida, se suspendía, luego el segundo programa se programaba, procesaba el búfer, etc. Los sistemas modernos son órdenes de magnitud mayor que los primeros sistemas Unix y puede ejecutar muchas tuberías en paralelo; pero para grandes cantidades de datos aún vería un efecto similar (y las variantes de este tipo de técnica se utilizan para el procesamiento de "grandes datos").

En tu ejemplo,

sed 'simplesubstitution' file | sort | uniq > file2

sed lee datos del file según sea necesario, luego lo escribe tan largo como sort está listo para leerlo; si sort no está listo, los bloques de escritura. De hecho, los datos viven en la memoria eventualmente, pero eso es específico de sort y sort está preparado para lidiar con cualquier problema (usará archivos temporales si la cantidad de datos para clasificar es demasiado grande).

Puede ver el comportamiento de bloqueo ejecutando

strace seq 1000000 -1 1 | (sleep 120; sort -n)

Esto produce una buena cantidad de datos y los canaliza a un proceso que no está listo para leer nada. durante los dos primeros minutos. Verá una serie de write las operaciones pasan, pero muy rápidamente seq se detendrá y esperará a que transcurran los dos minutos, bloqueado por el kernel (el write llamada del sistema en espera).


Linux
  1. Cómo limitar el uso de la CPU de un proceso en Linux

  2. Cómo aumentar el límite de memoria de PHP

  3. Linux:¿limitar el uso de memoria para un solo proceso de Linux?

  4. Cómo encontrar el uso de la memoria del usuario en Linux

  5. ¿Cómo se informa el uso de la memoria en Linux?

Cómo verificar el uso de memoria en Linux

Cómo verificar el uso de memoria en Debian 10

Cómo encontrar los principales procesos en ejecución por uso de memoria

¿Cómo interpretar el uso de memoria superior/htop?

Cómo ordenar el comando superior según el uso de memoria

¿Cómo perfilar el uso de la memoria?