Pergunta

Eu tenho um servidor TCP escrito em C # que processa os dados POST enviados a ele. Atualmente ele trabalha muito bem a menos que uma grande quantidade de dados (ou seja, maior do que 1GB) é enviado para ele, então ele fica sem memória (I guardar tudo na memória como um array de bytes (com um intermediário de uma lista de DTO)). Para arquivos grandes agora eu escorrer para o disco e, em seguida, passar o nome do arquivo ao redor com a intenção de fazer streaming-lo do disco.

Atualmente todas as minhas rotinas são escritas para esperar matrizes de bytes que, em retrospectiva, foi um pouco míope. Se eu apenas converter o bytearray a um memorystream que vai dobrar o uso de memória? Eu acho que re-escrever o meu código para trabalhar em um memorystream vai me permitir a re-uso quando estou lendo um fluxo de disco?

Desculpem a perguntas estúpidas, eu nunca estou certo quando c # tem uma cópia dos dados ou quando é preciso uma referência.

Foi útil?

Solução

Se você passar um byte[] em um MemoryStream, em seguida, ele irá copiar os dados inicialmente (no construtor), mas contanto que você soltar o byte[] pode ser lixo coletado. Inerentemente não há "dobrar" (especialmente se você pode definir o tamanho corretamente para começar, e escrever diretamente para o Stream vez do byte[]).

Eu totalmente dizer interruptor para Stream (mas única uso Stream na API - nada específico moer; seu código consumindo não precisa saber qual o tipo). Mais importante ainda, você pode optar por usar o NetworkStream (para ler directamente a partir do socket) ou FileStream (se você quiser para o buffer para o disco), ou MemoryStream se você quiser tampão em processo. Você também vai precisar para se certificar de que você lê que o volume de dados através de código baseado em fluxo. Iteradoras blocos (yield return) pode ser muito útil aqui, tal como podem os métodos LINQ Enumerable (excepto para OrderBy, GroupBy, etc, que tampão).

Nem a passagem de um byte[] nem passar um Stream faz qualquer coisa para se copiado, como eles são referência tipos -. A única coisa copiada é a referência (4 ou 8 bytes, dependendo x86 / x64)

Outras dicas

A MemoryStream é apenas um invólucro de fluxo em torno de um array de bytes, assim você não vai estar ganhando qualquer coisa usando-o.

O que você precisa fazer (para arquivos grandes, pelo menos) é aberto um FileStream e despejar seus dados em que. Em um nível mais baixo que você tem que ler X bytes de sua conexão e, em seguida, escrever isso imediatamente ao seu fluxo de arquivo. Desta forma, você não vai estar puxando em um show completo na memória, mas apenas alguns bytes de cada vez.

Seja ou não este vai ser fácil de fazer depende de como o servidor TCP está codificada.

Uma vez que um byte é um tipo de valor, se você passá-lo para uma função sem a palavra-chave ref você estará lidando com uma cópia de cada vez. Se você passá-lo com a palavra-chave ref, vai levar uma referência para o array de bytes originais.

A memorystream é um tipo de referência, de modo que não irá copiar os dados, mas você está passando em torno de uma referência a esses dados, para que o seu uso de memória não vai duplo em cima de usar isso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top