La cosa importante da capire sulla memoria virtuale è che è, ehm, virtuale.
Ad esempio, un processo potrebbe pensare che abbia 20 MiB di memoria virtuale. Tuttavia, 5 MiB di questo potrebbero essere parte di un file mappato in memoria che non è stato caricato dal disco, 5 MiB potrebbe apparire come una grande area piena di zeri (ma potrebbe essere la stessa piccola area piena di zeri ripetuti all'infinito e oltre), 5 MiB potrebbero essere dati nella partizione di swap.
È tutto virtuale, il che significa che sembra che la RAM sia lì (anche quando non lo è).
Quando il processo tenta di accedere a qualcosa che in realtà non è presente, il kernel viene informato (ad esempio "errore di pagina") e fa tutto ciò che deve fare per mantenere l'illusione che la RAM sia sempre presente.
Ad esempio, se il processo legge alcuni dati dall'area che è in realtà un file mappato in memoria, il kernel potrebbe caricare 4 KiB dal file in memoria e lasciare che il processo ritenga che i dati siano sempre presenti. Se il processo scrive su quella grande area piena di zeri, il kernel potrebbe allocare una nuova piccola area (e riempirla di zeri) che il processo può modificare (senza rovinare altre aree di zeri). Allo stesso modo, se il processo tenta di leggere / scrivere su qualcosa che è attualmente in uno spazio di swap, il kernel lo recupera dallo swap.
Per fare in modo che ciò accada, il kernel potrebbe aver bisogno di più memoria. Quando esaurisce la memoria, il kernel può semplicemente copiare i dati su disco / spazio di swap e riutilizzare quella memoria. Ovviamente se una copia dei dati è già presente sul disco (ad esempio non è stata modificata poiché è stata caricata dal disco l'ultima volta) il kernel non ha nemmeno bisogno di farlo - può semplicemente riutilizzare immediatamente la memoria.
Quindi ... Potresti avere un processo con 2 GiB di spazio virtuale. In quel 2 GiB di spazio il processo potrebbe utilizzare solo 50 MiB di memoria virtuale. Di quel 50 MiB di memoria virtuale, potrebbero essere solo 10 MiB di RAM effettiva (e 40 MiB di "inganni").
Naturalmente (poiché il disco IO è più lento della RAM) la maggior parte dei trucchi influisce sulle prestazioni. I kernel cercano di essere intelligenti e cercano di mantenere i dati "più utili da usare" nella memoria per minimizzare l'effetto sulle prestazioni. Purtroppo, predire il futuro è difficile, quindi "cercare di conservare i dati più probabili da utilizzare in memoria" in genere finisce per essere più simile a "conservare effettivamente i dati utilizzati più di recente in memoria".
In ogni caso, il modo migliore per minimizzare il sovraccarico è avere una RAM sufficiente. Maggiore è il numero di RAM, minore è l'ingannevolezza del kernel da eseguire e più veloce sarà il processo. Fortunatamente, la maggior parte della memoria utilizzata dalla maggior parte dei processi non viene utilizzata molto spesso, quindi (a seconda del processo) è possibile ottenere abbastanza bene con solo metà della RAM.
Si noti inoltre che (in generale) le prestazioni peggiori potrebbero essere indesiderabili, ma può essere molto meglio di "processo in crash a causa di esaurimento della memoria".