Come si scrive la fine di un file aperto con FILE_FLAG_NO_BUFFERING?
Domanda
Sto usando VB6 e l'API Win32 per scrivere i dati in un file, questa funzionalità è per l'esportazione dei dati, quindi scrivere le prestazioni sul disco è il fattore chiave nelle mie considerazioni. Come tale sto usando le opzioni FILE_FLAG_NO_BUFFERING
e FILE_FLAG_WRITE_THROUGH
quando apro il file con una chiamata a CreateFile
.
FILE_FLAG_NO_BUFFERING
richiede che io usi il mio buffer e scriva i dati nel file in multipli delle dimensioni del settore del disco, questo non è un problema in generale, a parte l'ultima parte dei dati, che se è non un multiplo esatto della dimensione del settore includerà il riempimento del carattere zero del file, come posso impostare la dimensione del file una volta che l'ultimo blocco è stato scritto per non includere questi zero del carattere?
Posso usare SetEndOfFile
ma questo mi richiede di chiudere il file e riaprirlo senza usare FILE_FLAG_NO_BUFFERING
. Ho visto qualcuno parlare di NtSetInformationFile
ma non riesco a trovare come usare e dichiararlo in VB6. SetFileInformationByHandle
può fare esattamente quello che voglio, tuttavia è disponibile solo in Windows Vista, la mia applicazione deve essere compatibile con le versioni precedenti di Windows.
Soluzione
Non sono sicuro, ma SEI sicuro che l'impostazione FILE_FLAG_NO_BUFFERING e FILE_FLAG_WRITE_THROUGH ti offrono le massime prestazioni?
Certamente i tuoi dati verranno colpiti il ??più presto possibile sul disco, ma quel genere di cose non aiuta le prestazioni, ma solo l'affidabilità per cose come i file journal che vuoi essere il più completo possibile in l'evento di un incidente.
Per una routine di esportazione dei dati come descritta, consentire al sistema operativo di bufferizzare i dati porterà probabilmente a MIGLIORI prestazioni, poiché le scritture verranno pianificate in linea con altre attività del disco, piuttosto che forzare il disco a tornare al file ogni scrittura.
Perché non esegui il benchmarking del tuo codice senza quelle opzioni? Lascia nella logica di padding a 0 byte per renderlo un test corretto.
Se si scopre che saltare queste opzioni è più veloce, è possibile rimuovere la logica di riempimento 0 e il problema relativo alle dimensioni del file si risolve da solo.
Altri suggerimenti
Credo che SetEndOfFile sia l'unico modo.
E sono d'accordo con Mike G. che dovresti mettere in panchina il tuo codice con e senza FILE_FLAG_NO_BUFFERING. Il buffering dei file di Windows sui moderni sistemi operativi è dannatamente efficace.
Beh, sono stupito! Usare il buffering di Windows invece di fare tutto da solo è MOLTO più veloce. Ho scritto un file da 1 GB con cui testare, usando il mio buffer e le opzioni FILE_FLAG_NO_BUFFERING
e FILE_FLAG_WRITE_THROUGH
sono durate in media 21.146 secondi, senza quelle impostazioni e usando il buffer di Windows il tempo medio è sceso a 13,53 secondi, ovvero oltre il 30% più veloce!
Nota per sé: non è necessario reinventare la ruota. ; -)
Grazie ' Mike G ' per la tua risposta rapida e accurata. E grazie anche a te " gabr ", non devi preoccuparti di SetEndOfFile
adesso.
Per un file da 1 GB, probabilmente il buffering di Windows sarà probabilmente più veloce, esp. se sta facendo molti piccoli IO. Se hai a che fare con file molto più grandi della RAM disponibile e stai eseguendo IO a blocchi di grandi dimensioni, i flag che stavi impostando produrranno un throughput migliore (fino a 3 volte più veloce per IO a blocchi di grandi dimensioni con thread pesante e / o casuale).