2010-09-20 5 views
14

Sto lavorando a un'applicazione che scrive sequenzialmente un file di grandi dimensioni (e non legge affatto), e vorrei usare posix_fadvise() per ottimizzare il comportamento del filesystem.Che posix_fadvise() si occupa della scrittura sequenziale di file?

La descrizione della funzione nella manpage suggerisce che la strategia più appropriata sarebbe POSIX_FADV_SEQUENTIAL. Tuttavia, la descrizione dell'implementazione di Linux dubita che:

Sotto Linux, POSIX_FADV_NORMAL imposta la finestra di lettura rapida sulla dimensione predefinita per il dispositivo di supporto; POSIX_FADV_SEQUENTIAL raddoppia questa dimensione e POSIX_FADV_RANDOM disabilita completamente il file readahead.

Dato che sto scrivendo solo dati (anche sovrascrivendo i file), non mi aspetto alcun readahead. Dovrei quindi continuare con il mio POSIX_FADV_SEQUENTIAL o meglio usare POSIX_FADV_RANDOM per disabilitarlo?

Come su altre opzioni, ad esempio POSIX_FADV_NOREUSE? O forse non usare posix_fadvise() per scrivere?

risposta

5

Tutto dipende dalla località temporale dei dati. Se la tua applicazione non avrà bisogno dei dati subito dopo la sua scrittura, puoi andare con POSIX_FADV_NOREUSE per evitare di scrivere nella cache del buffer (in modo simile al flag da open()).

+8

Si noti che POSIX_FADV_NOREUSE non è implementato nel kernel di Linux. – smoors

0

Per quanto riguarda le scritture, penso che si possa semplicemente fare affidamento sullo scheduler del disco del SO del sistema operativo per fare la cosa giusta.

Si tenga presente che mentre lo posix_fadvise è specificamente in grado di fornire suggerimenti sul kernel sui futuri modelli di utilizzo del file, il kernel ha anche altri dati per aiutarlo.

Se non si apre il file per la lettura, è necessario leggere i blocchi solo quando sono stati scritti parzialmente. Se si dovesse troncare il file a 0, non è nemmeno necessario farlo (hai detto che stavi sovrascrivendo).

32

La maggior parte dei flag posix_fadvise() (ad esempio POSIX_FADV_SEQUENTIAL e POSIX_FADV_RANDOM) sono suggerimenti su readahead piuttosto che scrivere.

C'è qualche consiglio da Linus here e here su come ottenere buone prestazioni di scrittura sequenziale. L'idea è quella di spezzare il file in grande-ish (8MB) di Windows, quindi anello intorno facendo:

  • scrivere finestra N con write();
  • richiesta asincrona scrittura fuori dalla finestra N con sync_file_range(..., SYNC_FILE_RANGE_WRITE)
  • attendere che la scrittura-fuori dalla finestra N-1 per completare con sync_file_range(..., SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER)
  • finestra Goccia N-1 dal pagecache con posix_fadvise(..., POSIX_FADV_DONTNEED)

In questo modo non si hanno mai più di due finestre di dati nella cache della pagina, ma si ottiene comunque che il kernel scriva parte della pagecache su disco mentre si riempie la parte successiva.

+1

Fantastico, questo è quello che dovevo fare utee (https: // github.com/aktau/utee) non gira la cache ma resta veloce. Grazie! – Aktau