Ho sentito (l'ho letto su Internet da qualche parte) che mmap() è più veloce dell'IO sequenziale. È corretto? Se sì, allora perché è più veloce?
Può essere - ci sono pro e contro, elencati di seguito. Quando hai davvero motivo di preoccupartene, confronta sempre entrambi .
A prescindere dall'effettiva efficienza di I/O, ci sono implicazioni per il modo in cui il codice dell'applicazione tiene traccia di quando deve eseguire l'I/O e l'elaborazione/generazione dei dati, che a volte possono avere un impatto notevole sulle prestazioni.
- mmap() non sta leggendo in sequenza.2) mmap() deve recuperare dal disco stesso come read()3) L'area mappata non è sequenziale, quindi niente DMA (?).
Quindi mmap() dovrebbe effettivamente essere più lento di read() da un file? Quali dei miei presupposti di cui sopra sono sbagliati?
-
è sbagliato...
mmap()
assegna una regione dello spazio degli indirizzi virtuali corrispondente al contenuto del file ... ogni volta che si accede a una pagina in quello spazio degli indirizzi, viene trovata la RAM fisica per supportare gli indirizzi virtuali e il contenuto del disco corrispondente viene inserito in quella RAM. Pertanto, l'ordine in cui vengono eseguite le letture dal disco corrisponde all'ordine di accesso. È un meccanismo di I/O "pigro". Se, ad esempio, avevi bisogno di indicizzare in un'enorme tabella hash che doveva essere letta dal disco, allorammap
l'inserimento del file e l'avvio dell'accesso significa che l'I/O del disco non viene eseguito in sequenza e può quindi comportare un tempo trascorso più lungo fino a quando l'intero file non viene letto in memoria, ma mentre ciò accade le ricerche hanno esito positivo e il lavoro dipendente può essere intrapreso, e se parti del file non sono mai effettivamente necessarie, non vengono lette (consentire la granularità delle pagine del disco e della memoria e che anche quando si utilizza la mappatura della memoria molti sistemi operativi consentono di specificare alcuni suggerimenti per migliorare le prestazioni / efficienza della memoria sul pianificato modelli di accesso in modo che possano leggere in anticipo in modo proattivo o rilasciare la memoria in modo più aggressivo sapendo che è improbabile che tu ci ritorni). -
assolutamente vero
-
"L'area mappata non è sequenziale" è vaga. Le regioni mappate in memoria sono "contigue" (sequenziali) nello spazio degli indirizzi virtuali. Abbiamo discusso che l'I/O del disco è sequenziale sopra. Oppure stai pensando ad altro? Ad ogni modo, mentre le pagine vengono violate, possono effettivamente essere trasferite utilizzando DMA.
Inoltre, ci sono altri motivi per cui la mappatura della memoria può superare le normali prestazioni di I/O:
- c'è meno copia:
- spesso le routine a livello di sistema operativo e libreria passano i dati attraverso uno o più buffer prima che raggiungano un buffer specificato dall'applicazione, l'applicazione quindi alloca dinamicamente lo spazio di archiviazione, quindi copia dal buffer I/O a quello spazio di archiviazione in modo che i dati siano utilizzabili dopo il file la lettura è completata
- la mappatura della memoria consente (ma non forza) l'utilizzo sul posto (puoi semplicemente registrare un puntatore e possibilmente la lunghezza)
- continuare ad accedere ai dati sul posto rischia di aumentare i mancati riscontri nella cache e/o lo scambio successivo:la mappa di file/memoria potrebbe essere più dettagliata delle strutture di dati in cui potrebbe essere analizzata, quindi i modelli di accesso sui dati al suo interno potrebbero avere più ritardi sbagliare in più pagine di memoria
- la mappatura della memoria può semplificare il lavoro di analisi dell'applicazione consentendo all'applicazione di trattare l'intero contenuto del file come accessibile, piuttosto che preoccuparsi di quando leggere un altro buffer pieno
- l'applicazione rimanda maggiormente alla saggezza del sistema operativo per quanto riguarda il numero di pagine che si trovano nella RAM fisica in un singolo momento, condividendo efficacemente una cache del disco ad accesso diretto con l'applicazione
- come commenti di benefattore di seguito, "usando la mappatura della memoria in genere usi meno chiamate di sistema"
- se più processi accedono allo stesso file, dovrebbero essere in grado di condividere le pagine fisiche di supporto
Ci sono anche i motivi per cui mmap
potrebbe essere più lento - leggi qui il post di Linus Torvald che parla di mmap
:
... i giochi da tavolo di pagine insieme all'errore (e anche solo alla mancanza di TLB) l'overhead è facilmente superiore al costo di copiare una pagina in un buon modo di streaming...
E da un altro dei suoi post:
- costi di installazione e smontaggio abbastanza evidenti. E intendo notevole . È come seguire le tabelle delle pagine per annullare la mappatura di tutto in modo pulito. È la contabilità per mantenere un elenco di tutte le mappature. È il flush TLB necessario dopo aver annullato la mappatura.
- l'errore di pagina è costoso. È così che la mappatura viene popolata, ed è piuttosto lenta.
Linux ha "hugepages" (quindi una voce TLB per 2MB, invece che per 4kb) e persino Transparent Huge Pages, dove il sistema operativo tenta di usarle anche se il codice dell'applicazione non è stato scritto per utilizzarle esplicitamente.
FWIW, l'ultima volta che questo si è verificato per me al lavoro, l'input mappato in memoria è stato dell'80% più veloce di fread
et al per la lettura di record di database binari in un database proprietario, su Linux a 64 bit con file da ~170 GB.
mmap()
può condividere tra processi.- Il DMA verrà utilizzato quando possibile. DMA non richiede memoria contigua:molte schede di fascia alta supportano DMA scatter-gather.
- L'area di memoria può essere condivisa con la cache dei blocchi del kernel, se possibile. Quindi c'è la copia del locatore.
- Memoria per
mmap
è allocato dal kernel, è sempre allineato.