Come può Windows scaricare la RAM completa nel file di ibernazione così velocemente?


65

Stavo leggendo un articolo che spiegava la procedura di ibernazione in Microsoft Windows. I punti principali che ne esco sono

  1. Windows scarica l'intera RAM (dopo averla eventualmente elaborata) nel hiberfil.sysfile.
  2. Durante l'avvio, viene letto il file di ibernazione e i contenuti vengono caricati nella RAM.

La mia domanda è quando di solito copio un file di dimensioni, diciamo 1 GB, ci vogliono circa 2 minuti per completarlo.

Tuttavia, quando Windows sta scrivendo il file di ibernazione (durante la procedura di ibernazione), l'intero processo dura forse 10-15 secondi. Perché c'è una tale differenza nella velocità di scrittura?

La mia dimensione della RAM è di 4 GB. (Non sto parlando della tecnologia di avvio rapido.)

benchmark:

  1. Copia di file da 1 GB dal disco 1 al disco 2 (esterno): 2,3 minuti.
  2. Ibernazione del sistema: 15 secondi.

3
Non conosco la risposta, ma scommetto che se hai controllato il libro Windows Internals "Chapter 13: Startup and Shutdown" ti direbbe (se avessi il libro da solo controllerei).
Scott Chamberlain,

2
Questa è una buona domanda Quando l'ibernazione fu implementata per la prima volta nel 1998, non fu così veloce.
Gabe,

22
@coder: il sistema NT si assicura che hyberfil.sys abbia tutto lo spazio allocato e che l'intero file non sia frammentato. In quella condizione non ci sono salti di testa sul disco rigido durante l'operazione. In questo modo otterrai velocità effettive come 150Mo / s. Puoi ricontrollare ciò che ho detto fsutil.
user2284570

3
Il disco esterno è in genere più lento del disco interno.
Harry Johnston

2
@EricLippert - sicuramente non memorizza tutta la RAM, ma ciò non lo spiega ancora. Ho regolarmente pochi gigabyte di RAM attiva che deve essere memorizzata (VS2013 o Eclipse + poche altre cose richiedono un sacco di RAM) e vengono archiviati alla velocità che mi sembra maggiore della velocità di scrittura teorica del mio non SSD guidare.
Assapora il

Risposte:


45

Questa è probabilmente una risposta tripla.

Una cosa che potrebbe essere in gioco qui è il nuovo Hybrid Shutdown in Windows che chiude efficacemente le tue applicazioni, ti disconnette e quindi procede a ibernare il nucleo del sistema operativo. Già avere questi dati salvati significherebbe che non è necessario "ri-ibernarli" potenzialmente.

La seconda cosa sarebbe che l'ibernazione non avrebbe bisogno di salvare le pagine di memoria che sono state paginate nel file di scambio o che non sono in uso (questo sarebbe uno dei motivi per riempire in modo aggressivo il file di scambio e conservare anche i dati in memoria) .

Il terzo sarebbe che anche i dati del file di ibernazione siano compressi . Combinalo con il mio secondo punto e se hai solo un piccolo set di dati da esportare che contiene dati altamente comprimibili (gli eseguibili generalmente vengono compressi bene), la quantità di dati da uscire nel file di ibernazione può essere sostanzialmente inferiore rispetto al set di lavoro di dati. Si noti che, come indicato nei commenti, le cache dei file e altri dati buffer non necessari potrebbero essere facilmente eliminati senza effetti negativi per ridurre la quantità di dati da scaricare nel file di ibernazione.

Inoltre, gli attuali dischi rigidi sono abbastanza veloci. Con un disco con una scrittura sostenuta nell'ordine di 100 MB / s si sarebbe in grado di scrivere (non compresso) 4 GB di RAM in meno di un minuto. Poiché l'ibernazione può essere eseguita come ultima cosa dopo aver sospeso tutti i processi dell'utente e prima di sospendere la CPU, il sistema operativo avrà generalmente la piena velocità di scrittura del disco. Questa è una cosa che il tuo semplice benchmark non avrà e la copia da disco a disco sarà potenzialmente più lenta della semplice scrittura della RAM su disco.

Combina queste cose e la quantità di dati da scrivere nel file di ibernazione potrebbe essere piuttosto piccola, potenzialmente dell'ordine di 1 GB e verrebbe probabilmente scritta su un grande blocco continuo in meno di 10 secondi.


37
Oppure, per renderlo più chiaro: probabilmente la tua RAM non è piena. I buffer vengono svuotati e la cache viene scartata durante l'ibernazione. Solo la memoria effettivamente utilizzata dalle applicazioni deve essere scritta su disco. L'arresto ibrido riduce la quantità di memoria in uso disconnettendo l'utente.
Daniel B,

2
Le pagine non sporche sono un'affermazione più generale di "paginazione nel file di scambio", inclusi gli eseguibili. (Poiché gli eseguibili sono in qualche modo frammentati sul disco, ciò potrebbe rallentare il riattivazione.) Inoltre, è possibile che i buffer di file puliti possano essere eliminati anche se non fanno parte di un file mappato in memoria.
Paul A. Clayton,

3
@ user2284570 dal documento che ho collegato in quella risposta "Windows supporta l'ibernazione copiando i contenuti della memoria su disco. Il sistema comprime i contenuti della memoria prima di conservarli sul disco, il che riduce lo spazio su disco richiesto a meno della quantità totale di memoria fisica sul sistema ".
Mokubai

4
@ user2284570: Questo perché lo scenario peggiore è la compressione 1: 1. Windows deve assicurarsi che ci sia abbastanza spazio (riservato) in hyberfil.sys per qualsiasi possibile configurazione di memoria, anche se ha bisogno solo di un decimo della dimensione della RAM per un determinato letargo. Aggiungete a ciò che una buona parte dell'utilizzo della RAM sono i file caricati in memoria (eseguibili, risorse ...), ma ancora mappati dall'HDD, e si può davvero risparmiare molta scrittura. Chiedi a un programma di generare 4 GiB di dati crittografici casuali nella RAM e l'ibernazione richiede molto più tempo - e anche allora, alcuni di essi potrebbero essere stati scambiati.
Luaan,

3
@ user2284570: il file è così grande da garantire spazio sul disco per archiviare tutta la memoria. Non tutto quello spazio è effettivamente utilizzato in letargo. A volte il file sarà (diciamo) contenuto di memoria compressa al 7%, spazzatura al 93%.
psmears,

31

Innanzitutto, la quantità di RAM che deve essere salvata è sorprendentemente piccola. In effetti, solo il set di pagine sporche mappate ("writeback pigro") deve essere svuotato, così come tutte le pagine private che sono state scritte e trasferito codice eseguibile devono essere scritte.

  • I segmenti .text degli eseguibili sono sempre supportati dalla mappatura dei file. Questo vale anche per almeno alcune DLL (ma non tutte, dipende dal fatto che debbano essere ricollocate).
  • La memoria che è supportata in modo simile dai mapping dei file può essere scartata (si presume che non sia CoW o RW e sporca).
  • Il writeback pigro dovrà ancora verificarsi, ma a parte questo, le cache possono essere scartate.
  • La memoria che è stata allocata ma non è stata scritta (di solito la maggior parte dei dati dell'applicazione!) È supportata dalla pagina zero e può essere scartata.
  • La maggior parte delle pagine di memoria che si trovano nello stato "standby" (il set di lavoro residente per processo effettivo su Windows è sorprendentemente piccolo, solo 16 MB) sarà stato copiato nel file di pagina in background ad un certo punto e può essere scartato .
  • Le aree di memoria mappate da determinati dispositivi come la scheda grafica potrebbero (eventualmente) non dover essere salvate. A volte gli utenti sono sorpresi di aver inserito 8GiB o 16GiB in un computer e 1GiB o 2GiB sono semplicemente "spariti" senza una ragione apparente. Le principali API grafiche richiedono che le applicazioni siano in grado di rendere i contenuti del buffer non validi "in determinate condizioni" (senza dire esattamente cosa significhi). Non è quindi irragionevole aspettarsi che anche la memoria bloccata dal driver grafico venga scartata. Lo schermo diventerà comunque scuro, dopo tutto.

In secondo luogo, contrariamente alla copia di un file, il dumping dell'insieme di pagine RAM che devono essere salvate sul disco è una singola scrittura sequenziale e contigua dal punto di vista dell'unità. L'API Win32 espone anche una funzione a livello di utente proprio per questa operazione. Gather write è supportato direttamente dall'hardware e funziona in modo rapido poiché il disco è fisicamente in grado di accettare i dati (il controller estraerà direttamente i dati tramite DMA).
Esistono una serie di condizioni preliminari affinché funzioni (come allineamento, dimensione del blocco, pinning) e non funziona bene con la memorizzazione nella cache e non esiste un "lazy writeback" (che è un'ottimizzazione molto desiderabile durante il normale funzionamento ).
Questo è il motivo per cui non tutti scrivonofunziona sempre così. Tuttavia, quando il sistema sta salvando il file di ibernazione, tutte le condizioni preliminari vengono soddisfatte automaticamente (tutti i dati sono allineati, dimensionati e bloccati) e la memorizzazione nella cache è diventata irrilevante perché il computer verrà spento tra un momento.

Terzo, fare una sola scrittura contigua è molto favorevole sia per i dischi rotanti che per i dischi a stato solido.

Il file di scambio e il file di ibernazione sono in genere alcuni dei primi file creati e riservati sul disco. Di solito ne hanno uno, al massimo due frammenti. Pertanto, a meno che i settori non siano danneggiati e il disco non debba riallocare settori fisici, una scrittura sequenziale logica si traduce in una scrittura sequenziale fisica su un disco rotante.

Non sono necessarie operazioni di lettura-modifica-scrittura sul disco quando viene scritta un'enorme quantità di dati sequenziali e contigui. Questo problema è meno pronunciato su un disco rigido rotante che può scrivere singoli settori che sono piuttosto piccoli (Se non si scrivono singoli byte, cosa che la cache di solito impedisce, il dispositivo non deve recuperare il contenuto originale e riscrivere la versione modificata.) .
Questo è, tuttavia, qualcosa che è molto evidente su SSD in cui ogni scrittura significa che ad esempio un blocco da 512 kB (che è un numero normale, ma potrebbe essere più grande) deve essere letto e modificato dal controller e riscritto in un altro bloccare. Mentre in linea di principio è possibile scrivere (ma non sovrascrivere) unità più piccole su dischi flash, puoi sempre e solo cancellare blocchi enormi, è come funziona l'hardware. Questo è il motivo per cui gli SSD vanno molto meglio con enormi scritture sequenziali.


Anche se una DLL viene trasferita, l'unica cosa necessaria per riportarla è l'indirizzo trasferito. Il trasferimento è un processo deterministico e può essere ripetuto.
Salterio del

"Riunisci a scrivere"? Vuoi dire "Piuttosto, scrivi"?
Peter Mortensen,

3
@PeterMortensen: No, intendo davvero radunare la scrittura (al contrario della lettura scatter). Ciò significa scrivere su un singolo file mentre si raccolgono i dati da più posizioni. Fornisci una serie di strutture ognuna delle quali contiene un indirizzo iniziale e una lunghezza (con requisiti di allineamento rigorosi). Il sistema operativo li passa al controller e l'hardware fa il resto.
Damon,

1
@MSalters: Ma il trasferimento crea una copia privata della pagina, ed è quindi estremamente difficile determinare se sono state apportate altre modifiche alla copia privata. Contrasta con le mappature che non richiedevano correzioni e usa copia su scrittura. Se vengono apportate altre modifiche, ci sarà una copia privata. In caso contrario, la pagina sarà comunque configurata per CoW.
Ben Voigt,

1
@MSalters Potrebbe essere un processo deterministico, ma ciò non implica che il codice di ibernazione operi sullo stesso livello dello stack software del linker. Se l'ibernazione è a livello di kernel e il collegamento è a livello utente, l'ibernazione non può fare ipotesi su ciò che fa il linker.
Kasperd,

10

Non scarica l'intera RAM al momento dell'ibernazione.

Avrà già una grande parte della RAM già duplicata sul disco. Ciò non solo consente all'ibernazione di verificarsi rapidamente, ma consente anche di rendere rapidamente disponibile la memoria per i nuovi programmi (in modo che possano avviarsi rapidamente).

Pertanto deve solo scrivere una piccola parte dei 4 GB e ciò può essere fatto in 10-15 secondi.

Da microsoft :

Quando la RAM è insufficiente (ad esempio, i commit commit è maggiore della RAM installata), il sistema operativo tenterà di mantenere una certa frazione di RAM installata disponibile per l'uso immediato copiando le pagine di memoria virtuale che non sono in uso attivo nel file di paging . Pertanto, questo contatore non raggiungerà lo zero e non è necessariamente una buona indicazione se il sistema è a corto di RAM.


2

Oltre a tutto quanto sopra, penso che ci siano alcuni altri fattori in gioco.

Uno è che, quando si copia un file, il file deve essere letto e scritto; hybernation richiede solo la scrittura del file. È, per definizione, già in memoria!

Strettamente correlato a questo, quando si legge un file e lo si scrive allo stesso tempo, per risparmiare memoria, il processo è: leggere un blocco, scrivere un blocco, aggiornare la directory (per mostrare la nuova dimensione); leggere un pezzo, scrivere un pezzo, aggiornare la directory.

Ogni volta che ti sposti da una parte del disco a un'altra (ad es. Leggi il file a per scrivere il file b, scrivi il file b per scrivere la directory e scrivi la directory per leggere il prossimo blocco) il disco deve cercare - sposta le testine, consentire alle teste di stabilizzarsi, attendere che arrivi la parte giusta del disco. Questo è uno dei vantaggi di un disco a stato solido: la ricerca non richiede tempo. Durante il letargo, i dati vengono scritti end-to-end. Il file di ibernazione (swap) è pre-allocato, quindi non è necessario aggiornare la directory (non si sta modificando la dimensione del file di ibernazione, ma solo il contenuto).

E infine, il tuo computer ha sospeso tutte le altre attività - questa è l'unica cosa che sta facendo (dubito che questo farà molta differenza, ma è destinato a farne alcune!). Anche cose come la gestione della memoria e la commutazione delle attività sono sospese.


E 'destinato a fare una grande differenza!
Lightness Races con Monica

@LightnessRacesinOrbit: la contesa della CPU non farà praticamente alcuna differenza. La mancanza di contese di I / O è un grosso problema, ma questa risposta ha già affermato che la ricerca di uccisioni delle prestazioni e la ricerca, non la mancanza di larghezza di banda complessiva, è il problema principale della contesa di I / O.
Ben Voigt,

@BenVoigt: Sì, sono d'accordo. E quando hai 40 processi tutti cercando di fare cose su disco, questo aumenterà sostanzialmente la ricerca del disco. (tl; dr Non stavo parlando della contesa della CPU)
Lightness Races con Monica

@LightnessRacesinOrbit: Sembra ... insolito anche durante il normale funzionamento (tutto tranne entrare e uscire dal letargo). So che quando rilevo un'attività in background che colpisce il disco, disinstallo la ventosa e la sostituisco con qualcosa che accede al disco solo quando glielo chiedo.
Ben Voigt,

@BenVoigt: sembra improbabile. La registrazione dei demoni è il controesempio più ovvio, seguito da elementi come gli aggiornamenti dei file di drift di ntpd. Non sto affermando che uno di questi esempi abbia un grande effetto qui, ma non credo sia ragionevole aspettarsi che nessuna attività in background tocchi il disco in modo autonomo.
Lightness Races con Monica

0

Ciò è probabilmente dovuto al fatto che la RAM ha una velocità di input / output molto più rapida rispetto al disco rigido, quindi la RAM è in grado di inviare le cose in esso con la stessa velocità con cui il disco rigido può leggere.

Quando si copiano file, si è anche limitati da vari fattori: la velocità del disco, se deve leggere dentro e fuori sullo stesso disco ci vorrà più tempo, la velocità limitata della connessione (se all'unità esterna), controllandolo non sovrascrive nulla ecc


9
ma il sistema operativo deve ancora scrivere i dati della RAM da 4 GB sul disco, che è regolato dal collo di bottiglia degli I / O
codificatore

Anche assumendo parametri favorevoli implica che durante l'ibernazione la velocità di scrittura del mio disco va da 40 MB / sa ~ 260 MB / s. Può essere corretto?
coder

1
Probabilmente - non dovrebbe esserci troppo collo di bottiglia di I / O in quanto deve solo scrivere i dati (probabilmente c'è qualcosa in atto in modo che sappia che non sovrascriverà roba e dove mettere i dati in modo che non lo faccia bisogno di leggere troppo il disco). Sul mio laptop (Linux dual booted) posso usare dd if=/dev/zero of=/tmp/output.img bs=8k count=256ke ottenere 1862606848 bytes (1.9 GB) copied, 1.81605 s, 1.0 GB/s, quindi sembra possibile (aggiungerò che la copia di Windows dei file sembra richiedere comunque inutilmente tempo).
Wilf

Puoi anche ottenere un trasferimento molto più veloce quando copi i file su Internet locale. Inoltre potrebbe non essere necessario copiare tutte le cose nella RAM: alcuni dei dati nella RAM potrebbero essere solo memorizzati nella cache e non necessari per ripristinare il sistema al risveglio dal letargo.
Wilf

Ho appena provato il benchmark dd sul mio sistema. Non è mai andato oltre i 52 MB / s: / (vecchia macchina) Tuttavia credo che "probabilmente c'è qualcosa in atto, quindi sa che non sovrascriverà roba e dove mettere i dati in modo che non debba leggere il disco troppo " È la chiave per la velocità veloce.
coder
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.