GNU/Linux >> Linux Esercitazione >  >> Linux

In che modo le pipeline limitano l'utilizzo della memoria?

Brian Kernighan spiega in questo video l'attrazione dei primi Bell Labs per i piccoli linguaggi/programmi basati su limiti di memoria

Una grande macchina sarebbe 64 k-byte – K, non M o G – e quindi questo significava che ogni singolo programma non poteva essere molto grande, e quindi c'era una tendenza naturale a scrivere programmi piccoli, e quindi il meccanismo pipe, fondamentalmente input reindirizzamento dell'output, ha permesso di collegare un programma all'altro.

Ma non capisco come ciò possa limitare l'utilizzo della memoria considerando il fatto che i dati devono essere archiviati nella RAM per essere trasmessi tra i programmi.

Da Wikipedia:

Nella maggior parte dei sistemi simili a Unix, tutti i processi di una pipeline vengono avviati contemporaneamente [enfasi mia] , con i loro flussi opportunamente collegati e gestiti dallo scheduler insieme a tutti gli altri processi in esecuzione sulla macchina. Un aspetto importante di questo, che distingue le pipe Unix dalle altre implementazioni delle pipe, è il concetto di buffering:ad esempio un programma di invio può produrre 5000 byte al secondo e un programma ricevente può essere in grado di accettare solo 100 byte al secondo, ma non i dati vengono persi. L'output del programma di invio viene invece mantenuto nel buffer. Quando il programma ricevente è pronto per leggere i dati, il programma successivo nella pipeline legge dal buffer. In Linux, la dimensione del buffer è 65536 byte (64 KB). È disponibile un filtro di terze parti open source chiamato bfr per fornire buffer più grandi, se necessario.

Questo mi confonde ancora di più, poiché vanifica completamente lo scopo dei piccoli programmi (sebbene sarebbero modulari fino a una certa scala).

L'unica cosa a cui posso pensare come soluzione alla mia prima domanda (i limiti di memoria sono problematici a seconda delle dimensioni dei dati) sarebbe che i set di dati di grandi dimensioni semplicemente non venivano calcolati all'epoca e il vero problema che le pipeline dovevano risolvere era il quantità di memoria richiesta dai programmi stessi. Ma dato il testo in grassetto nella citazione di Wikipedia, anche questo mi confonde:poiché un programma non viene implementato alla volta.

Tutto ciò avrebbe molto senso se si utilizzassero i file temporanei, ma ho capito che le pipe non scrivono su disco (a meno che non venga utilizzato lo scambio).

Esempio:

sed 'simplesubstitution' file | sort | uniq > file2

Mi è chiaro che sed sta leggendo il file e lo sputa riga per riga. Ma sort , come afferma BK nel video collegato, è un punto fermo, quindi tutti i dati devono essere letti in memoria (o no?), quindi vengono passati a uniq , che (a mio avviso) sarebbe un programma di una riga alla volta. Ma tra la prima e la seconda pipe, tutti i dati devono essere in memoria, no?

Correlati:Ubuntu:eseguire un comando quando è inserito un CD/DVD/BD?

Risposta accettata:

I dati non devono essere archiviati nella RAM. Le pipe bloccano i loro scrittori se i lettori non ci sono o non riescono a tenere il passo; sotto Linux (e la maggior parte delle altre implementazioni, immagino) c'è del buffering ma non è richiesto. Come accennato da mtraceur e JdeBP (vedi la risposta di quest'ultimo), le prime versioni di Unix hanno eseguito il buffering su disco, ed è così che hanno contribuito a limitare l'utilizzo della memoria:una pipeline di elaborazione potrebbe essere suddivisa in piccoli programmi, ognuno dei quali elaborerebbe alcuni dati , entro i limiti dei buffer del disco. I piccoli programmi richiedono meno memoria e l'uso di pipe significava che l'elaborazione poteva essere serializzata:il primo programma veniva eseguito, riempiva il buffer di output, veniva sospeso, quindi il secondo programma veniva programmato, elaborava il buffer, ecc. I sistemi moderni sono ordini di grandezza maggiore rispetto ai primi sistemi Unix e può far scorrere molti tubi in parallelo; ma per enormi quantità di dati vedresti comunque un effetto simile (e varianti di questo tipo di tecnica vengono utilizzate per l'elaborazione dei "big data").

Nel tuo esempio,

sed 'simplesubstitution' file | sort | uniq > file2

sed legge i dati da file se necessario, quindi lo scrive finché sort è pronto a leggerlo; se sort non è pronto, i blocchi di scrittura. I dati alla fine risiedono effettivamente nella memoria, ma questo è specifico di sort e sort è pronto ad affrontare qualsiasi problema (userà file temporanei se la quantità di dati da ordinare è troppo grande).

Puoi vedere il comportamento di blocco eseguendo

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

Questo produce una discreta quantità di dati e li convoglia a un processo che non è pronto a leggere nulla per i primi due minuti. Vedrai un numero di write le operazioni vanno a buon fine, ma molto rapidamente seq si fermerà e attenderà che trascorrano i due minuti, bloccato dal kernel (il write la chiamata di sistema è in attesa).


Linux
  1. Utilizzo della memoria di Linux

  2. Come limitare l'utilizzo della CPU di un processo in Linux

  3. limitare l'utilizzo della memoria in R sotto Linux

  4. Come trovare l'utilizzo della memoria dell'utente in Linux

  5. Limita l'utilizzo della memoria per un singolo processo Linux

Come controllare l'utilizzo della memoria in Linux

Come controllare l'utilizzo della memoria in Debian 10

Come trovare i migliori processi in esecuzione in base all'utilizzo della memoria

Come interpretare l'utilizzo della memoria top/htop?

Come ordinare il comando superiore in base all'utilizzo della memoria

Come profilare l'utilizzo della memoria?