2013-08-19 12 views
6

Questa domanda è nel seguito di una precedente domanda che ho postato: Windows fsync (FlushFileBuffers) performance with large files. Dove ho trovato una possibile soluzione ma anche nuove domande.Spiegazione/informazioni richieste: Windows scrive prestazioni I/O con "fsync" (FlushFileBuffers)

Durante l'analisi comparativa di diversi scenari per le scritture fsynced, ho riscontrato numerosi risultati sorprendenti. Spero che qualcuno possa aiutarmi a spiegare o indicarmi le informazioni che spiegano questi risultati.

Ciò che fa questo benchmark è la scrittura di blocchi casuali (pagine 4096 byte di grandi dimensioni) in un file sequenzialmente in gruppi di 8 pagine (32 K) e quindi lo svuotamento delle scritture. Scrive un totale di 200000 pagine, per un totale di 800 MB e 25000 scarichi. Le dimensioni del file sono impostate sulla lunghezza finale prima di iniziare le scritture.

Esso supporta un totale di 4 opzioni, di cui vengono eseguiti tutte le combinazioni:

  • di eseguire un "fsync"/FlushFileBuffers operazione (FS) dopo aver scritto un batch o un colore normale (NS).
  • Per scrivere un singolo byte nell'ultima posizione del file prima di iniziare a scrivere (LB) o lasciare il file vuoto (E).
  • Per utilizzare le scritture del buffer normale (B) o non buffer/writethrough (WT) (utilizzando FILE_FLAG_NO_BUFFERING e FILE_FLAG_WRITE_THROUGH).
  • Per scrivere direttamente sul flusso di file, tramite l'handle di file (F) o scrivere indirettamente sul file utilizzando una mappa di memoria (MM).

La tabella seguente riepiloga le mie conclusioni sul mio sistema (laptop Win 7 a 64 bit con disco a fuso lento) per tutte le combinazioni di queste opzioni.

Benchmark results for all combinations of options

Quello che ho trovato è che la prestazione di scritture tamponati "fsynced" decresce esponenzialmente con la dimensione del file da un erogato incredibilmente basso che rende questa operazione non è fattibile in combinazione con file di grandi dimensioni. Se il file ha il suo ultimo byte scritto (opzione LB), il throughput è ancora più basso, quindi temo che in caso di scenari di scrittura casuali anziché sequenziali, le prestazioni saranno ancora più drammatiche.

Sorprendentemente, tuttavia, con I/O unbuffered/writethrough il throughput rimane costante, indipendentemente dalla dimensione del file. Inizialmente (i primi 100-200 MB) ha un throughput inferiore rispetto alle scritture bufferizzate, ma dopo questo il throughput medio raggiunge rapidamente e termina la scrittura degli 800 MB sostanzialmente più veloci. Ancora più sorprendente è che se il file ha il suo ultimo byte scritto, il throughput aumenta di un fattore 2.

Quando si scrive sul file attraverso un file mappato in memoria, si osserva la stessa diminuzione esponenziale delle prestazioni, anche nel caso in cui il file è stato aperto con flag unbuffered/writethrough. E anche qui, le prestazioni sono peggiori se il file avesse un byte scritto nella sua ultima posizione.

UPDATE Sulla base di spiegazioni di Howard here e here, ho nuovamente eseguita la prova senza creare un nuovo file prima di iniziare le operazioni di scrittura (cioè l'apertura del, file completo scritto esistente e sovrascrivendo). Ho aggiornato il codice nella mia domanda originale per riflettere le modifiche apportate per questo test. I risultati sono parzialmente in linea con la sua spiegazione e le scoperte su Linux. Ma ci sono alcune eccezioni degne di nota. La tabella seguente fornisce i risultati, evidenzia in rosso cambiamenti significativi, evidenziazioni blu in cui non si sono verificati cambiamenti e questo è sorprendente (es.non in linea con le aspettative se gli effetti menzionati nella spiegazione di Howard fossero gli unici in gioco).

Results when overwriting existing file

Per il tamponata scrive su file (cioè non attraverso memmap) con un filo "fsync", la prestazione è cambiato da decadimento esponenziale a un andamento costante. Tuttavia, ora richiede molto più tempo rispetto agli scenari di test precedenti. Il throughput è costante di 1,5 MB/s, dove prima era iniziato a circa 20 MB/s per decadere esponenzialmente a circa 1,5 MB/s. Sembrerebbe che una possibile spiegazione sia che i metadati del file vengano anche scaricati su ogni colore, causando una rivoluzione completa del disco per cercare la posizione dei metadati.

Per gli scenari "write through", i risultati per la scrittura dell'ultimo byte o meno, sono ora identici, in linea con quanto previsto dalla spiegazione di Howard.

Le scritture sulla mappa della memoria, tuttavia, con un'eccezione degna di nota, non sono realmente cambiate e questo è sorprendente. Mostrano ancora lo stesso decadimento esponenziale delle prestazioni in scrittura (a partire da circa 20 MB/s in decadimento a 1,8 MB/s). Ciò suggerirebbe che è in gioco un meccanismo diverso. L'unica eccezione notevole è se il file sottostante è stato creato senza FILE_FLAG_WRITE_THROUGH e vengono eseguiti "flush" fsync. Questo scenario mostra ora una prestazione costante (scarsa) con un throughput di circa 1,6 MB/s. Dato che avevo qualche dubbio, ripenso a questo scenario più volte, dando lo stesso risultato ogni volta.

di capire un po 'di più, ho anche reran questo test utilizzando un file più piccolo (50000 pagine, pari a 200 MB), per confermare, che le prestazioni fsync (per buffer di I/O) in realtà non dipende dalle dimensioni del file . I risultati sono mostrati di seguito, con quelli che meritano un'attenzione speciale evidenziata in rosso.

Results on smaller file

Questi risultati correlano bene con quanto visto per il file più grande. I cambiamenti notevoli sono che le scritture sono un po 'più performanti per quelle che sono evidenziate, dove sembrano raggiungere un limite di circa 7 MB/s.

Riassumendo come altamente speculativi conclusioni basate su osservazioni sul mio sytem finora:

  • "fsync" prestazioni su finestre sul file con buffer IO (cioè senza bandiere FILE_FLAG_WRITE_THROUGH) è esponenziale decrescente con il numero di byte già scritti nel file. La ragione sembra essere la necessità di scaricare ogni volta i metadati del file, il che fa sì che un disco cerchi all'inizio del file.
  • Le prestazioni "fsync" su Windows durante la scrittura su un file mappato in memoria mostrano anche prestazioni in declino esponenziale. Al momento non ho una spiegazione per i meccanismi esatti che causano questo.

Data questa prestazione osservata, almeno per il mio caso d'uso, queste due opzioni di I/O non rappresenterebbero soluzioni fattibili.

Come da Greg's suggestion io eseguire nuovamente il test con le finestre disk caching spento, e io anche eseguire di Howard fornito benchmark code per escludere la possibilità che i risultati non sono allineate a causa di errori nella mia.

UPDATE 2 Ho completato i test e sto attualmente compilando i risultati.Per non scrivere "la storia completa di" sostituirò i contenuti correnti di questa domanda con un riassunto dei risultati, dei risultati e alcune conclusioni. Le risposte di Howard su questa domanda e la possibilità di eseguire il suo codice di riferimento c accanto al codice .NET è stato molto utile. I risultati di tali applicazioni si correlano abbastanza bene. La risposta di Rlb mi ha aiutato a capire meglio quali sono i "numeri ragionevoli" relativi ai dischi. Grazie.

Una parte della domanda rimane senza risposta. Particolarmente correlato all'osservazione delle prestazioni (e delle dimensioni del file dipendenti) durante la scrittura su una mappa di memoria. Potrebbe essere correlato a ricerche/flush di metadati, ma non mi è ancora chiaro il motivo/come.

+0

Se si chiude tmpfile poco prima il vostro rapporto di raccolta tempistica definitiva, ciò altera i numeri? Un paio dei tuoi risultati sono interessanti, quindi potresti provare anche a riprodurli. L'ordine in cui esegui gli scenari ha qualche effetto? – rlb

+0

Il file temporaneo è chiuso. Questa costruzione viene utilizzata per creare un nuovo file vuoto, impostarne la lunghezza e, facoltativamente, riempire l'ultimo byte. Dopo che è chiuso. Il file viene riaperto prima di iniziare le scritture. – Alex

+0

@rlb e nessun ordine non ha alcun effetto reale. Poiché ogni volta creiamo il file da zero e lo riempiamo con byte casuali, non si verifica alcun effetto di memorizzazione nella cache. L'esecuzione di uno scenario indipendente dà praticamente lo stesso risultato. – Alex

risposta

4

Si nota una diminuzione esponenziale della velocità nell'esecuzione della sincronizzazione poiché questi non sono carichi di lavoro puramente sequenziali come credi. Poiché stai iniziando con un nuovo file ogni volta, le tue scritture stanno aumentando il file e i metadati devono essere aggiornati nel filesystem. Ciò richiede più ricerche e, man mano che il file cresce, i richiami dalla fine del file ai metadati richiedono sempre più tempo. Ho anche postato questo messaggio per un'altra domanda per errore, vedere la risposta completa qui: https://stackoverflow.com/a/18429712/894520

0

Provare a disattivare la cache del disco e il repost?

Altrimenti queste metriche non hanno senso (Fsync e write through potrebbero non colpire effettivamente il disco). Windows di default permette la memorizzazione nella cache del disco e controller di cache ..

Greg

+0

FlushFileBuffers deve svuotare la cache del controller. Questo è il punto dell'esercizio. –

+0

Greg, nella tua esperienza è il caso che i comandi "SYNCHRONIZE CACHE" o "FLUSH CACHE" non vengano rispettati dai dispositivi quando viene emesso 'FlushFileBuffers'? O che le cache del file system del sistema operativo non vengono scaricate come risultato di 'FlushFileBuffers'. Cioè quale sarebbe la logica per disabilitare del tutto il caching del disco di Windows? – Alex

+0

O è collegato al fatto che fino a Win 7/Server 2008 R2 incluso usava solo "Force Unit Access" per svuotare i metadati NTFS? – Alex