2013-02-11 8 views
7

Su Linux a 64-bit (come Amazon EC2 esempio), ho bisogno di caricare un paio di grandi file binari in memoria. Qual è il modo più veloce?In C++, qual è il modo più veloce per caricare un grande file binario (da 1 GB a 4 GB) in memoria?

  • ifstream
  • fread
  • POSIX aperta
  • POSIX mmap (in realtà non caricare l'intero file in memoria, che danneggia le prestazioni)
  • qualcos'altro?

Inoltre, il nodo può o meno lanciare questo eseguibile una seconda volta, quindi è utile se il file viene caricato ancora più velocemente nei tentativi successivi. Una sorta di fase di precaricamento potrebbe persino funzionare.

+2

Come stai programmando per accedere al file? Hai bisogno di TUTTO il file in memoria prima di poterlo utilizzare? Hai intenzione di leggere e scrivere, o semplicemente di leggere? –

+0

Perché non iniziare con un benchmark delle prime 4 opzioni? Penso che puoi misurarlo abbastanza facilmente e probabilmente dovrai farlo comunque: quando si tratta di prestazioni, non dovresti fidarti ciecamente di tutto senza misurare. –

+0

Sei sicuro che usare mmap sia effettivamente più lento? La memoria del tuo processo può essere scambiata allo stesso modo del contenuto del file. Inoltre, per mmap potresti provare il flag MAP_POPULATE per preimpostare le pagine del mapping. –

risposta

7

Il tempo sta per essere dominato da disco I/O, in modo che si utilizza API non è importante quanto a pensare a come funziona un disco. Se si accede a un (supporto rotante) del disco in modo casuale costerà 3 a 9 millesimi di secondo a cercare ... una volta che il disco è in streaming si può sostenere circa 128 MB/sec, che è come i bit veloci arriveranno al largo della testina del disco. Il collegamento SATA o il bus PCIe hanno una larghezza di banda molto superiore (da 600 a 2000 MB/s). Linux ha una cache di pagina in memoria dove mantiene una copia delle pagine sul disco, quindi è possibile che la macchina disponga di una quantità adeguata di RAM, i tentativi successivi saranno rapidi, anche se si accede ai dati casualmente. Quindi il consiglio è leggere grandi blocchi alla volta. Se vuoi davvero accelerare il caricamento iniziale, puoi usare mmap per mappare l'intero file (1 GB-4 GB) e avere un thread di supporto che legge il 1 ° byte di ogni pagina in ordine.

Si può leggere di più su disk drive performance characteristics here.

Si può leggere di più sul page cache here.

1

Dato l'informazioni di cui sopra, direi mmap è un buon candidato. Ci sono alcuni motivi che dicono che: 1. Ti dà l'intero file senza realmente caricare (parte) del file fino a quando è effettivamente necessario che una parte. Questo è un vantaggio per il caricamento veloce, ma se alla fine avremo passato ogni byte [o toccato su ogni sezione 4KB del file], allora non c'è una grande differenza. 2. Il mmap copierà solo i dati una sola volta dal disco alle tue pagine. Questo è più efficiente nei miei test rispetto alla lettura usando fread o read in Linux (si noti anche che la differenza tra fread e read per letture ragionevolmente grandi può essere ignorata.Un po 'di overhead in più nelle funzioni FILE in C. C++ flussi per aggiungere un un bel po 'di overhead, tuttavia, nella mia esperienza [ho provato varie forme di questo più volte ormai]

Come sempre, il benchmarking brilla sempre chiedendo su Internet. Così puoi trovare ciò che ho detto sopra non è giusto nei vostri circostanze e come ha sottolineato, una volta che il codice è sufficientemente buono, alcun overhead nel codice viene sminuito dalla velocità che i dischi in grado di fornire i dati -. anche se si dispone di un sistema RAID molto di fantasia con un sacco di parallelo (SSD ?) dischi, ecc., eventualmente il trasferimento del disco s peed sarà dove si trova il collo di bottiglia. Tutto quello che puoi fare a quel punto è cercare di avere il minor numero possibile di overhead e ottenere i dati dall'applicazione il più rapidamente possibile dopo che il disco ha consegnato i dati.

Un buon punto di riferimento per "byte al secondo" è quello di utilizzare dd if=/dev/zero of=somefile bs=4K count=1M (che scrive un file, è possibile che si desideri dd if=somefile of=/dev/null bs=4K per vedere quanto è possibile leggere dal disco.

1

Puoi provare mmap con la bandiera MAP_POPULATE. Dubito che tu possa farlo più velocemente.