Si tengo tres valores separados que todo podría caber en 32 bits, tiene sentido utilizar un uint para almacenarlos?

StackOverflow https://stackoverflow.com/questions/3587593

Pregunta

Lo que quiero decir es, decir que tengo un struct para representar algunos datos y se ve así:

struct LilStruct
{
    public readonly short A;
    public readonly byte B;
    public readonly byte C;

    public LilStruct(short a, byte b, byte c)
    {
        A = a;
        B = b;
        C = c;
    }
}

A short y dos valores byte todos podrían encajar en 32 bits. Lo que me pregunto es (para fines de alineación, rendimiento, lo que sea) si sería realmente tiene sentido para almacenar estos datos en el siguiente formato en su lugar:

struct LilStruct
{
    private readonly uint _value;

    public LilStruct(short a, byte b, byte c)
    {
        _value = ((uint)a << 16) | ((uint)b << 8) | (uint)c;
    }

    public int A
    {
        get { return (int)(_value >> 16); }
    }

    public int B
    {
        get { return (int)(_value >> 8) & 0x000000FF; }
    }

    public int C
    {
        get { return (int)(_value & 0x000000FF); }
    }
}

Es este sentido? ¿Cuáles serían las ventajas / desventajas?

¿Fue útil?

Solución

En .NET, cuando se va a utilizar un struct de todos modos, que puede así decorar la estructura con StructLayoutAttribute como esto:

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct LilStruct
{
    public readonly short A;
    public readonly byte B;
    public readonly byte C;

    public LilStruct(short a, byte b, byte c)
    {
        A = a;
        B = b;
        C = c;
    }
}

Esto tendrá el efecto de que los campos están dispuestos de forma secuencial, por ejemplo, B campo comenzará en el desplazamiento 16.

Un valor de 1 para Pack significa que los campos se alinean en los límites byte.

Otros consejos

Sólo se debe considerar abarrotar múltiples valores en un uint si los valores están estrechamente vinculados entre sí, por lo general pasa alrededor juntos, y nunca o muy raramente modificarse con independencia entre sí son. El costo de desembalaje y volver a empaquetar la uint con el fin de modificar su valor hace que este muy caro (en el tamaño del código y tiempo de ejecución) en comparación con sólo el almacenamiento de tres bytes por separado.

Cuando se ejecuta en un microdispositivo con un total de 10 k bytes de RAM, el embalaje como esto podría valer la pena porque la memoria es más precioso que la velocidad de ejecución. En un PC de escritorio normal o dispositivo de teléfono móvil, incluso, esta empaquetadura es probable que no vale la pena el esfuerzo.

Se podría quedarse con su definición, estructura, y aplicar la atributo StructLayout con un valor de 1. Pero, de hecho StructLayoutAttribute.Pack , es probable que ahorrar un poco de memoria a expensas de la velocidad de acceso, ya que de esta manera los datos no se establece en la memoria de una manera que es más eficiente para el acceso. El compilador normalmente sería diseñar la memoria de una manera que es eficiente para el acceso y no se echaría a perder demasiada memoria automáticamente.

Este enfoque, al menos, mantener su código más comprensible que el enfoque de desplazamiento de bits usted propuso (que podría o no podría, de hecho, todavía será similar a lo que el compilador de código de máquina generaría a partir del código de bytes).

Lo que se encontrará es una solución de compromiso simple entre el tamaño de los objetos de datos en memoria y el costo de procesamiento. Si la memoria no es una preocupación real, simplemente puede ser más barato que tirar más memoria RAM en su máquina.

Existen algunos casos en los que la pena cosas de meter en un entero. El espacio de almacenamiento por sí sola no suele ser una buena razón, pero si los valores se va a utilizar en conjunto como por ejemplo, una clave para un diccionario, un diccionario (de enteros, lo que) será mucho más rápido que un diccionario (De SomeStructure, que sea).

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