2009-05-31 14 views
6

Qual è la differenza - prestazioni-saggio - tra la lettura da una presa 1 byte alla volta e la lettura in grande blocco?Lettura da una presa 1 byte alla volta contro lettura in grande blocco

Ho un'applicazione C++ che deve prelevare pagine da un server Web e analizzare la pagina ricevuta riga per riga. Attualmente sto leggendo 1 byte alla volta fino a quando non incontro un CRLF o il massimo di 1024 byte è raggiunto.

Se la lettura di una grande porzione (ad es. 1024 byte alla volta) è molto più efficace sul piano delle prestazioni, qualsiasi idea su come ottenere lo stesso comportamento che ho attualmente (cioè essere in grado di memorizzare ed elaborare 1 linea html in un tempo - fino al CRLF senza consumare i byte successivi ancora)?

EDIT:

non posso permettermi troppo grandi buffer. Sono in un budget di codice molto ristretto poiché l'applicazione viene utilizzata in un dispositivo incorporato. Preferisco mantenere solo un buffer a dimensione fissa, preferibilmente per contenere una linea html alla volta. Questo rende il mio parsing e l'altra elaborazione facile come sono ogni volta che provo ad accedere al buffer per l'analisi, posso presumere che sto elaborando una linea html completa.

Grazie.

+0

Potrebbe fornire maggiori dettagli sul dispositivo incorporato? Ha anche un sistema operativo su di esso? –

risposta

4

Se si sta leggendo direttamente dalla presa, e non da una rappresentazione superiore livello intermedio che possono essere memorizzati, quindi, senza alcun dubbio, è meglio leggere completamente i 1024 byte, inserirli nella RAM in un buffer e quindi analizzare i dati dalla RAM.

Perché? La lettura su un socket è una chiamata di sistema e causa uno switch di contesto su ogni lettura, che è costoso. Per saperne di più: IBM Tech Lib: Boost socket performances

+0

+1 - Mi piace la tua argomentazione sul perché la lettura in grandi blocchi è migliore per quanto riguarda le prestazioni. Penso di potermi accontentare della risposta di Neil Butterworth per risolvere la mia seconda preoccupazione. =) –

1

primo e più semplice:

cin.getline(buffer,1024); 

In secondo luogo, di solito tutto IO è tamponato in modo non c'è bisogno di preoccuparsi troppo iniziare

In terzo luogo, processo CGI di solito costa molto di più quindi l'elaborazione di ingresso (a meno che non è enorme il file ) ... Quindi potresti non pensarci.

1

G'day,

Uno dei grandi successi di performance facendolo un byte alla volta è che il vostro contesto sta andando di volta in volta dall'utente sistema più e più volte. E oltre. Non efficiente affatto.

L'acquisizione di un grosso pezzo, in genere fino a una dimensione MTU, è misurabilmente più efficiente.

Perché non scansionare il contenuto in un vettore e scorrere su quello che cerca \ n di separare il tuo input in linee di input web?

HTH

applausi,

+0

Sì, a seconda del numero di chiamate, il sovraccarico relativo causato dalle chiamate di funzione potrebbe effettivamente diventare significativo a un certo punto. – none

5

non posso commentare su C++, ma da altre piattaforme - Sì, questo può fare una grande differenza; in particolare nella quantità di interruttori che il codice deve eseguire e il numero di volte in cui deve preoccuparsi della natura asincrona dei flussi ecc.

Ma il vero test è, ovviamente, il profilo. Perché non scrivere un'app di base che sforna un file arbitrario utilizzando entrambi gli approcci e testarlo per alcuni file tipici ... l'effetto è di solito sorprendente, se il codice è legato all'IO. Se i file sono di piccole dimensioni e la maggior parte del tempo di esecuzione dell'app viene spesa durante l'elaborazione di i dati una volta che sono in memoria, non si noterà alcuna differenza.

1

Non si sta leggendo un byte alla volta da un socket, si sta leggendo un byte ad un atime dal sistema di I/O C/C++, che se si utilizza CGI avrà alreadato tutto l'input da la presa.L'intero punto di I/O bufferizzato consiste nel rendere i dati disponibili al programmatore in un modo che è conveniente per loro elaborare, quindi se si desidera elaborare un byte alla volta, andare avanti.

Modifica: Riflettendo, non è chiaro dalla domanda se si sta implementando CGI o semplicemente utilizzandolo. Puoi chiarire questo postando uno snippet di codice che indica come stai leggendo il singolo byte.

Se si sta leggendo direttamente il socket, è sufficiente leggere l'intera risposta al GET in un buffer e quindi elaborarlo. Questo ha numerosi vantaggi, tra cui prestazioni e facilità di codifica.

Se si linitted di un piccolo tampone, quindi utilizzare algoritmi tampone classici come:

getbyte: 
    if buffer is empty 
     fill buffer 
     set buffer pointer to start of buffer 
    end 
    get byte at buffer pointer 
    increment pointer 
+0

No. Sto leggendo da una presa. Sto facendo richiesta HTTP GET al server web e legge la risposta da un socket. Lo faccio perché ho bisogno del contenuto dinamico completamente renderizzato e analizzato. –

+0

Penso che potrei accontentarmi di questo algoritmo con una piccola modifica. Posso avere due buffer di dimensione fissa. Uno per leggere un intero (diciamo 512 byte), lo scannerizza e memorizza una singola linea html completa su un altro buffer a cui ho potuto accedere facilmente nei miei altri metodi di analisi. Potrei avere una routine di lettura socket più efficiente e potrei mantenere la facilità di elaborazione che ho adesso (vale a dire i miei altri metodi assumendo una linea html completa). Grazie. =) –

0

Non c'è alcuna differenza a livello di sistema operativo, i dati sono bufferizzati comunque. L'applicazione, tuttavia, deve eseguire più codice per "leggere" i byte uno alla volta.

1

È possibile aprire il file di socket descritpor con la funzione fdopen(). Quindi hai bufferato IO in modo da poter chiamare fgets() o simile su quel descrittore.

+0

-1 per il suggerimento gets(). – bk1e

+0

scusate, volevo dire fgets(), modificato la mia risposta ora :-( – codymanix

+0

Come hai potuto !! – LukeN