Je veux savoir s'il y a une surcharge lors de la conversion entre des tableaux d'octets et des Streams (en particulier MemoryStreams lors de l'utilisation de MemoryStream.ToArray() et MemoryStream(byte[]). Je suppose que cela double temporairement l'utilisation de la mémoire.

Par exemple, je lis comme un flux, je convertis en octets, puis je convertis à nouveau en flux. Mais se débarrasser de cette conversion d'octets nécessitera un peu de réécriture. Je ne veux pas perdre de temps à le réécrire si cela ne fait aucune différence.

1
Dynamiquel 28 août 2020 à 19:44

2 réponses

Meilleure réponse

Donc, oui ... vous avez raison de supposer que ToArray duplique la mémoire dans le flux.

Si vous ne souhaitez pas faire cela (pour des raisons d'efficacité), vous pouvez modifier les octets directement dans le flux. Regarde ça:

// create some bytes: 0,1,2,3,4,5,6,7...
var originalBytes = Enumerable.Range(0, 256).Select(Convert.ToByte).ToArray();

using(var ms = new MemoryStream(originalBytes)) // ms is referencing bytes array, not duplicating it
{
    // var duplicatedBytes = ms.ToArray(); // copy of originalBytes array

    // If you don't want to duplicate the bytes but want to
    // modify the buffer directly, you could do this:

    var bufRef = ms.GetBuffer();

    for(var i = 0; i < bufRef.Length; ++i)
    {
        bufRef[i] = Convert.ToByte(bufRef[i] ^ 0x55);
    }

    // or this:
    /*
    ms.TryGetBuffer(out var buf);
    for (var i = 0; i < buf.Count; ++i)
    {
        buf[i] = Convert.ToByte(buf[i] ^ 0x55);
    }*/

    // or this:
    /*
    for (var i = 0; i < ms.Length; ++i)
    {
        ms.Position = i;
        var b = ms.ReadByte();

        ms.Position = i;
        ms.WriteByte(Convert.ToByte(b ^ 0x55));
    }*/
}

// originalBytes will now be 85,84,87,86...

ETA:

Édité pour ajouter des exemples de Blindy. Merci! - J'ai totalement oublié GetBuffer et je n'avais aucune idée de TryGetBuffer

2
Andy 28 août 2020 à 17:49

MemoryStream(byte[]) provoque-t-il une copie mémoire?

Non, c'est un flux non redimensionnable et, en tant que tel, aucune copie n'est nécessaire.

MemoryStream.ToArray() provoque-t-il une copie mémoire?

Oui, de par sa conception, il crée une copie du tampon actif. Il s'agit de couvrir le cas redimensionnable, où le tampon utilisé par le flux n'est pas le même tampon que celui initialement fourni en raison de réallocations pour augmenter / diminuer sa taille.

Alternatives à MemoryStream.ToArray() qui ne provoquent pas de copie mémoire?

Bien sûr, vous avez MemoryStream.TryGetBuffer (out ArraySegment<byte> buffer), qui renvoie un segment pointant vers le tampon interne, qu'il soit redimensionnable ou non. S'il n'est pas redimensionnable, c'est un segment dans votre tableau d'origine.

Vous avez également MemoryStream.GetBuffer, qui renvoie la totalité du tampon interne. Notez que dans le cas redimensionnable, ce sera beaucoup plus grand que l'espace de flux utilisé réel, et vous devrez vous ajuster pour cela dans le code.

Et enfin, vous n'avez pas toujours besoin d'un tableau d'octets, parfois vous avez juste besoin de l'écrire dans un autre flux (un fichier, une socket, un flux de compression, une réponse Http, etc.). Pour cela, vous disposez de MemoryStream.CopyTo[Async], qui n'effectue aucune copie.

2
Blindy 28 août 2020 à 17:39