PDA

Visualizza la versione completa : [OT] Ricevere (molto) testo da una socket e scriverlo su file


closerToTheEdge
03-09-2011, 14:39
Ciao a tutti.

Questo non è un vero e proprio problema di programmazione, però tento lo stesso a porvi la domanda per chiedervi consiglio.

Un server deve ricevere, via socket, un testo (che potrebbe essere di pochi caratteri o un documento molto grande). Lo deve poi scrivere su un file di testo. Il punto è che lavoro in ambiente multithread, perciò ho necessità di mettere un lock in scrittura sul file stesso.

Il client, con le sue write() invia dati in 'pacchetti' di una certa dimensione predefinita, e ovviamente il server entra in un ciclo di read() in cui accetta questi pacchetti fino alla fine.

Il problema nasce qui: sarebbe meglio scrivere ogni singolo pacchetto ricevuto sul file oppure bufferizzare tutti i pacchetti in arrivo e scrivere tutto alla fine?

Questi i contro:
-se scrivo su file ogni singolo pacchetto, ci fosse qualche ritardo di rete tengo il file lockato troppo a lungo, a discapito degli altri thread che invece potrebbero scrivere nel frattempo.

-se bufferizzo tutti i pacchetti fino alla fine, il testo inviato dal client potrebbe essere di notevoli dimensioni e quindi occupare parecchia memoria.

C'è una via di mezzo? Io avevo pensato di scrivere temporaneamente i 'pacchetti' su un file temporaneo, che poi "riverso" tutto in una volta sul file di interesse alla chiusura della comunicazione. Quanto è conveniente?

MItaly
03-09-2011, 14:49
Scrivere i pacchetti su un file temporaneo è una sciocchezza, la situazione è identica che con un file normale.
Io scriverei i su file i blocchi che ricevi senza farmi troppi problemi, la libreria C in ogni caso bufferizza l'output prima di effettivamente chiamare la write sul file, e a sua volta il sistema operativo bufferizza le scritture su disco, per cui, a meno che le dimensioni dei tuoi blocchi non siano piccolissime (e a quel punto potrebbe diventare sensibile l'overhead delle chiamate a funzione) non dovresti avere problemi di performance in scrittura.
In ogni caso, il bottleneck nella tua applicazione suppongo sia sicuramente l'IO su rete, non l'IO su file, per cui non mi preoccuperei troppo di quest'ultimo.

closerToTheEdge
03-09-2011, 15:32
Ti ringrazio per la risposta.

Il mio problema non è tanto la bufferizzazione, quanto la durata del write-lock sul file.

Una volta che il thread1 inizia a scrivere il primo blocco del testo (ammesso che si scelga la soluzione di scrivere un blocco non appena arriva dalla rete), è impossibile che un thread2 (o qualunque altro) inizi la sua scrittura, in quanto il primo thread ha acquisito il lock.

Potrebbe verificarsi la situazione in cui il thread2, il thread3 ... e il threadn abbiano da scrivere solo pochi caratteri, ma non possono farlo in quanto il file è "occupato" dal thread1, che a sua volta aspetta i dati dalla rete (che è l'elemento con maggior ritardo, in questo caso).

Per questo mi chiedevo se magari non fosse il caso di ricevere TUTTI i dati dalla rete (ossia scrivere in un unico buffer tutti i pacchetti in arrivo dalla rete), e POI copiarli sul file con un'unica scrittura. In questo caso il problema sarebbe la dimensione dei dati da tenere in memoria centrale; tuttavia, il thread con meno cose da scrivere potrebbe assolvere immediatamente al suo compito.

MItaly
03-09-2011, 15:37
Uh, pardon, avevo letto male e non avevo colto il problema del multithreading. Ma c'è una cosa che non mi è chiara, perché tutti questi thread scrivono sullo stesso file? Voglio dire, anche se lasciamo da parte i problemi di lock, va bene che quando uno finisce di scrivere un altro a caso che ha dei dati da scrivere ce li attacca subito dopo? Non c'è un ordinamento di qualche genere?

closerToTheEdge
03-09-2011, 15:43
Non è richiesto nessun ordinamento (e per fortuna, aggiungerei :D ).

Se n client decidessero di scrivere nello stesso intervallo di tempo, non è importante l'ordine con cui i loro testi compaiono nel file del server. L'importante è che siano separati tra loro.

MItaly
03-09-2011, 15:47
Allora forse mi sa che la soluzione migliore è effettivamente avere un bufferone in cui tenere i dati in arrivo (magari una lista di stringhe, una per ogni "chunk" ricevuto), e scrivere tutto alla fine tenendo il lock sul file per il minor tempo possibile, prevedendo magari uno "sfogo" su un file temporaneo quando le dimensioni della lista iniziano a diventare eccessive (ma a meno che non ti arrivino "messaggi" da centinaia di MB credo sia un'inutile complicazione).

closerToTheEdge
03-09-2011, 15:56
Ti ringrazio davvero tanto per il consiglio.

Effettivamente anche nel caso avessi a che fare con decine di migliaia di caratteri, sarebbero "solo" qualche decina di KB che nell'economia del processo non dovrebbero essere eccessivi.

Comunque, tanto per concludere, nel caso in cui le dimensioni dovessero crescere, il consiglio è quello di creare un file-tampone per ogni thread (che ne abbia bisogno). Giusto?

MItaly
03-09-2011, 16:04
Sì, anche se comunque anche tenere tutto in memoria non è un grosso problema finché non si arriva a dimensioni paragonabili allo spazio di indirizzi del processo (2-4 GB sulle macchine a 32 bit, un numero ridicolmente grande su quelle a 64 bit), dato che se c'è poca memoria fisica il sistema operativo fa paging della memoria del tuo processo per i cavoli suoi.

Loading