Mi código utiliza MemoryStream para serializar/deserializar objetos a/desde la red. Me gustaría volver a utilizar un único MemoryStream en mi clase, en lugar de crear uno nuevo cada vez que lo necesito
para enviar algo sobre el alambre.

¿Alguien sabe cómo hacer esto?

Fragmento de código:

    //Serialize object to buffer
    public  byte[] Serialize(object value)
    {
        if (value == null)
            return null;
      MemoryStream _memoryStream = new MemoryStream();

        _memoryStream.Seek(0, 0);
        _bf.Serialize(_memoryStream, value);
        return _memoryStream.GetBuffer();
    }

    //Deserialize buffer to object
    public  object Deserialize(byte[] someBytes)
    {         
        if (someBytes == null)
            return null;
        MemoryStream _memoryStream = new MemoryStream();
        _memoryStream.Write(someBytes, 0, someBytes.Length);
        _memoryStream.Seek(0, 0);
        var de = _bf.Deserialize(_memoryStream);
        return de;
    }

Gracias!

¿Cuál es la razón para la reutilización de los arroyos? Suena como una manera bastante fácil de introducir memoryleaks y duro para depurar el código.
+1 al comentario de @Richard. No hacer esto a menos que usted tiene perfilado el código y encontró que se trata de una interpretación o ejecución o problema con la memoria.
Gracias, chicos. Supongo que me olvidé de lo que alguien dijo una vez sobre la optimización de……

OriginalEl autor Jacko | 2011-01-07

2 Comentarios

  1. 8

    Primero de todos tus serializar método tiene un error:

    Nota de que el buffer contiene asignado bytes que pueden ser utilizados. Por ejemplo, si la cadena «prueba» está escrito en el objeto MemoryStream, la longitud del búfer regresó de GetBuffer es de 256, no 4, con 252 bytes no utilizados. Para obtener sólo los datos en el buffer, utilice el método ToArray; sin embargo, el método ToArray crea una copia de los datos en la memoria.

    es decir, la matriz devuelve es mayor que los datos serializados

    Para deserializar usted puede construir una secuencia de memoria que utiliza el pasado en la serie, por lo que no se asignarán búferes internos. Pero a menos que tenga puntos de referencia que muestran que la memoria de la secuencia de asignación es realmente un cuello de botella que no me molestaría.

    Si usted realmente desea optimizar sus asignaciones de memoria tendrás la necesidad de reutilización de la byte[] de los buffers. Esto significa, en particular, la modificación de la api para trabajar con las subsecciones de las matrices de modo que el tamaño del mensaje y el tamaño de la matriz no necesitan ser idénticos.

    Los siguientes son los detalles de implementación que pueden cambiar en cualquier momento(y puede que ya los han cambiado desde que he leído sobre él):

    Seguro que no vale la pena molestarse si los búferes no terminan en el montón de objetos grandes. Si los objetos son pequeños van a ser barato recogidos en la siguiente Gen0 colección. El montón de objetos grandes en la otra mano directamente termina en Gen2. AFAIR objetos >250kB se asignan allí.

    Y, por supuesto, la reutilización de los búferes sin reducción de ellos puede ser una pérdida de memoria.

    +1 para la buena observación.
    Wow, gracias, CodeInChaos!! Me preguntaba por qué me estaba poniendo de 256 bytes de matrices.

    OriginalEl autor

  2. 12

    Reutilizar la misma MemoryStream no le da ninguna ventaja de rendimiento.

    Hay una razón por la MemoryStream no tiene un claro. Porque sería más caro claro es que para crear una nueva.

    Si usted mira la parte interna de la clase, se puede ver que se asigna un búfer, y al escribir, si su buffer se llena, se asigna amortiguador nuevo y copiar los bytes y, a continuación, lleva. De tal manera que el buffer es inmutable.

    Esto puede ser visto aquí en el ajuste de la capacidad, que es llamado por EnsureCapacity() en el momento de la escritura:

    public virtual int Capacity
    {
        get
        {
            if (!this._isOpen)
            {
                __Error.StreamIsClosed();
            }
            return (this._capacity - this._origin);
        }
        [SecuritySafeCritical]
        set
        {
            if (value < this.Length)
            {
                throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
            }
            if (!this._isOpen)
            {
                __Error.StreamIsClosed();
            }
            if (!this._expandable && (value != this.Capacity))
            {
                __Error.MemoryStreamNotExpandable();
            }
            if (this._expandable && (value != this._capacity))
            {
                if (value > 0)
                {
                    byte[] dst = new byte[value];
                    if (this._length > 0)
                    {
                        Buffer.InternalBlockCopy(this._buffer, 0, dst, 0, this._length);
                    }
                    this._buffer = dst;
                }
                else
                {
                    this._buffer = null;
                }
                this._capacity = value;
            }
        }
    }
    SetLength(0) es, efectivamente, un claro. Y me imagino que ofrece ventajas de rendimiento(para grandes buffers) mediante la reutilización de la solución tampón. Pero probablemente todavía no vale la pena.
    Gracias Aliostad. hace un montón de sentido.

    OriginalEl autor

Dejar respuesta

Please enter your comment!
Please enter your name here