Domanda

Ho un server TCP scritto in C # che elabora i dati POST inviati. Attualmente funziona bene a meno che una grande quantità di dati (cioè maggiore di 1 GB) viene inviato ad esso, allora esaurisce la memoria (I memorizzare tutto in memoria, come un array di byte (con un intermediario di un elenco DTO)). Per i file di grandi dimensioni ora a valle su disco e quindi passare il nome del file in giro con l'intenzione di flusso dal disco.

Al momento tutte le mie routine sono scritte aspettarsi array di byte, che, col senno di poi, era un po 'miope. Se ho appena convertire il ByteArray a un MemoryStream intende raddoppiare l'utilizzo della memoria? Penso riscrittura mio codice per lavorare su un MemoryStream mi permetterà di ri-uso quando sto leggendo un flusso dal disco?

Ci scusiamo per le domande stupide, non sono mai sicuro quando c # prende una copia dei dati o, quando ci vuole un punto di riferimento.

È stato utile?

Soluzione

Se si passa un byte[] in un MemoryStream, allora sarà copiare i dati inizialmente (nel costruttore), ma fino a quando si rilascia il byte[] può essere garbage collection. Intrinsecamente non c'è "raddoppio" (soprattutto se è possibile impostare la dimensione corretta per cominciare, e scrivere direttamente al Stream piuttosto che il byte[]).

Vorrei dire interamente interruttore per Stream (ma solo uso Stream nell'API - niente moer specifico; il codice di consumare non ha bisogno di sapere quale tipo). Ancora più importante, è possibile scegliere di utilizzare il NetworkStream (per leggere direttamente dalla presa) o FileStream (se si vuole tamponare su disco), o MemoryStream se si vuole tamponare in-process. È inoltre necessario assicurarsi di leggere che il volume dei dati tramite codice basato sul flusso. Blocchi Iterator (yield return) può essere molto utile qui, così come i metodi di LINQ Enumerable (ad eccezione di OrderBy, GroupBy, ecc, che buffer).

Né il superamento di un byte[] né il superamento di un Stream fa di tutto per essere copiati, in quanto sono di riferimento-tipi -. L'unica cosa copiato è il riferimento (4 o 8 byte, a seconda x86 / x64)

Altri suggerimenti

Un MemoryStream è solo un wrapper flusso attorno a un array di byte, in modo da non essere guadagnando nulla per utilizzarlo.

Quello che dovete fare (per i file di grandi dimensioni, almeno) è aperto un FileStream e scaricare i dati in questo. Ad un livello inferiore si deve leggere X byte dalla vostra connessione e poi scrivere che immediatamente al vostro flusso di file. In questo modo non sarà tirando in un concerto in memoria piena, ma solo pochi byte alla volta.

Se questo sarà facile da fare dipende da come il vostro server TCP è codificato.

Dal momento che un byte è un tipo di valore, se si passa a una funzione senza la parola chiave ref avrete a che fare con una copia ogni volta. Se si passa con la parola chiave ref, ci vorrà un riferimento alla matrice di byte originale.

Un MemoryStream è un tipo di riferimento, in modo da non copiare i dati, ma si sta passando intorno un riferimento a tali dati, in modo che l'uso di memoria non raddoppierà su utilizzando questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top