Pregunta

Tengo un servidor TCP escrito en C # que procesa datos POST enviados a él. Actualmente funciona bien a menos que una gran cantidad de datos (es decir, mayor que 1 GB) es enviado a él, entonces se queda sin memoria (almaceno todo en la memoria como una matriz de bytes (con un intermedio de una lista DTO)). Para archivos de gran tamaño ahora aguas abajo en el disco y luego pasar el nombre de archivo por ahí con la intención de streaming desde el disco.

Actualmente, todos mis rutinas están escritas esperar matrices de bytes, que, en retrospectiva, fue un poco miope. Si acabo de convertir el bytearray a un MemoryStream va a duplicar el uso de la memoria? Creo que volver a escribir el código para trabajar en un MemoryStream me permitirá volver a utilizarlo cuando estoy leyendo una corriente desde el disco?

Lo siento por las preguntas tontas, nunca estoy seguro de que cuando c # toma una copia de los datos o cuando se toma una referencia.

¿Fue útil?

Solución

Si pasa un byte[] en un MemoryStream, a continuación, se copian los datos de un principio (en el constructor), pero siempre y cuando se suelta el byte[] puede ser basura recogida. Inherentemente no hay una "duplicación" (sobre todo si se puede establecer el tamaño correcto para empezar, y escribir directamente a la Stream en lugar de la byte[]).

Yo diría totalmente interruptor para Stream (pero solamente Stream uso de la API - específica moer nada, su código de consumir no necesita saber qué tipo). Lo más importante, se puede optar por utilizar el NetworkStream (para leer directamente de la toma) o FileStream (si desea amortiguar el disco), o MemoryStream si quieres que se almacenarán en-proceso. Usted también tendrá que asegurarse de que lea ese volumen de datos a través de código basada en secuencias. bloques de iterador (yield return) puede ser muy útil en este caso, al igual que los métodos de LINQ Enumerable (a excepción de OrderBy, GroupBy, etc, que buffer).

Ni pasar un byte[] ni pasar un Stream hace cualquier cosa para copiado, ya que son de referencia de tipo -. Lo único copiado es la referencia (4 u 8 bytes, dependiendo de x86 / x64)

Otros consejos

A MemoryStream es sólo una envoltura de secuencia en torno a un conjunto de bytes, por lo que no será ganar nada con él.

Lo que hay que hacer (para archivos de gran tamaño por lo menos) es abrir una FileStream y volcar los datos en eso. En un nivel inferior hay que leer X bytes de su conexión y luego escribir que de inmediato a su secuencia de archivo. De esta manera no se le tira en un concierto completo en la memoria, pero sólo unos pocos bytes a la vez.

Si es o no será fácil de hacer depende de cómo se codifica el servidor TCP.

Dado que un byte es un tipo de valor, si se pasa a una función sin la palabra clave ref se le trata con una copia cada vez. Si pasa con la palabra clave ref, que va a tomar una referencia a la matriz de bytes originales.

A MemoryStream es un tipo de referencia, por lo que no copiará los datos, pero usted está pasando alrededor de una referencia a esos datos, por lo que su uso de la memoria no se duplicará en el uso de eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top