2012-03-12 21 views
12

Sto usando la funzione di I/O di basso livello 'write' per scrivere alcuni dati su disco nel mio codice (linguaggio C su Linux). Innanzitutto, accumulo i dati in un buffer di memoria, quindi utilizzo 'write' per scrivere i dati sul disco quando il buffer è pieno. Quindi qual è la dimensione del buffer migliore per "scrivere"? Secondo i miei test non è tanto più veloce, quindi sono qui per cercare la risposta.qual è la dimensione del buffer corretta per la funzione 'scrivi'?

+0

+1 per fare una buona domanda ... Ho sempre voluto conoscere la dimensione giusta per la funzione di scrittura .... – aProgrammer

+0

possibile duplicato di [Dimensione buffer ottimale per scrivere (2)] (http://stackoverflow.com/questions/8803515/optimum-buffer-size-for-write2) – Raedwald

risposta

3

Probabilmente vi sono alcuni vantaggi nell'effettuare scritture che sono multipli della dimensione del blocco del filesystem, specialmente se si sta aggiornando un file sul posto. Se scrivi meno di un blocco parziale in un file, il sistema operativo deve leggere il vecchio blocco, combinare i nuovi contenuti e quindi scriverlo. Ciò non accade necessariamente se si scrivono rapidamente piccoli pezzi in sequenza perché gli aggiornamenti verranno eseguiti sui buffer in memoria che verranno scaricati successivamente. Tuttavia, una volta ogni tanto si potrebbe innescare qualche inefficienza se non si sta compilando un blocco (e uno allineato correttamente: più dimensioni del blocco con un offset che è un multiplo della dimensione del blocco) con ciascuna operazione di scrittura.

Questo problema delle dimensioni del trasferimento non va necessariamente a finire con mmap. Se si mappa un file e quindi memcpy alcuni dati nella mappa, si sta creando una pagina sporca. Quella pagina deve essere svuotata in un secondo momento: è indeterminata quando. Se fai un altro memcpy che tocca la stessa pagina, quella pagina potrebbe essere pulita ora e la stai rendendo nuovamente sporca. Quindi viene scritto due volte. Le copie allineate alla pagina dei multipli, di una dimensione della pagina, saranno la strada da percorrere.

3

Si vorrà che sia un multiplo della dimensione della pagina della CPU, in modo da utilizzare la memoria nel modo più efficiente possibile.

Ma idealmente si preferisce utilizzare mmap, in modo che non si debba mai occuparsi dei buffer da soli.

+0

+1 per l'utilizzo di mmap –

+0

Quindi, se si desidera scrivere 3 GB di dati, è possibile creare un mmap da 3 GB? Haha. Potresti fare un mmap più piccolo e poi rimapparlo mentre avanzi nel file, il che è più complicato. Per quanto riguarda i buffer: beh, qual è il mmap? È una regione di memoria con un puntatore di base e un puntatore corrente che ti dice dove memorizzare il prossimo pezzo. E qual è la dimensione ideale per quelle operazioni memcpy? Se copi 300 byte qui, 300 byte lì, potresti attivare scarichi sub-ottimali. Cioè la CPU potrebbe prenderti mentre crei la stessa pagina sporca due volte e sciacquala due volte. – Kaz

+0

cosa succede se i dati da elaborare sono molto più grandi della RAM? –

1

Dipende dalla quantità di RAM, VM, ecc. Nonché dalla quantità di dati da scrivere. La risposta più generale è quella di valutare quale buffer funzioni meglio per il carico con cui si ha a che fare e utilizzare ciò che funziona meglio.

+1

qual è un buon modo per calcolare l'ammontare corretto dato tutto questo – pyCthon

+0

Iterate attraverso le diverse impostazioni per le dimensioni del buffer e confrontatelo? –

+0

che funziona immagino che mi stavo chiedendo se ci fosse una sorta di formula basata su ram, vm exc – pyCthon

3

Si potrebbe utilizzare BUFSIZ definita <stdio.h>

Altrimenti, utilizzare un piccolo multiplo della dimensione pagina sysconf(_SC_PAGESIZE) (ad esempio due volte tale valore). La maggior parte dei sistemi Linux ha pagine da 4Kbyte (che è spesso uguale o un piccolo multiplo della dimensione del blocco del filesystem).

Come altri ha risposto, utilizzando la chiamata di sistema mmap(2) potrebbe aiutare. I sistemi GNU (ad esempio Linux) hanno un'estensione: la seconda stringa di modalità di fopen può contenere l'ultimo m e quando ciò accade, la libc GNU tenta di mmap.

Se si trattano dati di dimensioni quasi pari alla RAM (o metà), è possibile anche utilizzare madvise(2) per ottimizzare le prestazioni di mmap.

Vedere anche this answer per una domanda del tutto simile alla vostra. (È possibile utilizzare 64 KB come dimensione del buffer ragionevole).

2

La dimensione "migliore" dipende molto dal file system sottostante.

I stat e fstat chiamate riempire in una struttura dati, struct stat, che comprende i seguenti campi:

blksize_t st_blksize; /* blocksize for file system I/O */ 

Il sistema operativo è responsabile per il riempimento di questo campo con un "buona dimensione" per) blocchi (scrittura.Tuttavia, è anche importante chiamare write() con memoria "ben allineata" (ad es. Il risultato delle chiamate malloc). Il modo più semplice per farlo è utilizzare l'interfaccia di streaming <stdio.h> fornita (con gli oggetti FILE *).

Utilizzando mmap, come in altre risposte qui, può anche essere molto veloce per molti casi. Si noti che non è adatto ad alcuni tipi di flussi (ad es. Prese e pipe).

+0

vuoi dire che fwrite è generalmente più veloce di scrivere con una dimensione buffer adeguata? –

+0

Non necessariamente "più veloce di", ma eseguirà rapidamente copie di blocco nello spazio utente secondo necessità. Inoltre, se hai bisogno di scrivere una serie di diverse stringhe brevi da varie posizioni, le riunirà tutte insieme e passerà un blocco di dimensioni appropriate al kernel, in una chiamata di sistema. (In alcuni casi è possibile ottenere un effetto simile con 'writev', ma in genere è più di quanto valga la pena, e anche allora il kernel tende a dover fare le stesse copie di memoria.) – torek

+0

Questo valore è destinato a essere esattamente questo, ma è risultato che se uso questo valore, è ancora più lento se ad es copiare i dati da A a B, perché devo fare più syscalls in questo modo. – glglgl

Problemi correlati