Se ho tre valori separati che potrebbe tutti in forma in 32 bit, ha senso utilizzare un uint per memorizzarle?

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

Domanda

Quello che voglio dire è, dire che ho un struct per rappresentare alcuni dati e sembra che questo:

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 e due valori byte poteva tutti in forma in 32 bit. Quello che mi chiedo è (per scopi di allineamento, prestazioni, a prescindere) se sarebbe effettivamente dare un senso a memorizzare questi dati nel seguente formato invece:

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); }
    }
}

E 'questo inutile? Quali sarebbero i vantaggi / svantaggi?

È stato utile?

Soluzione

In .NET, quando si intende utilizzare un struct in ogni caso, si può anche decorare la struct con StructLayoutAttribute in questo modo:

[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;
    }
}

Ciò avrà l'effetto che i campi sono disposti in sequenza, per esempio campo B avrà inizio alle 16 di offset.

Un valore pari a 1 per Pack significa che i campi sono allineati ai confini byte.

Altri suggerimenti

Si dovrebbe considerare solo stipare più valori in un uint se i valori sono strettamente legati l'uno all'altro, di solito passava in giro insieme, e non sono mai o molto raramente modificati indipendentemente l'uno dall'altro. Il costo di disimballaggio e imballaggio della uint per modificare il valore rende molto costoso (in formato codice e tempo di esecuzione) rispetto al solo memorizzare tre byte separatamente.

Quando in esecuzione su un microdispositivi con un totale di 10k byte di RAM, imballaggio come questo potrebbe essere la pena perché la memoria è più preziosa velocità di esecuzione. Su un normale PC desktop o dispositivo telefono anche cellulare, questo imballaggio è probabilmente non vale la pena.

Si poteva stare con la vostra definizione struct, e applicare il attributo StructLayout un valore StructLayoutAttribute.Pack di 1. Ma in realtà, è probabilmente risparmiare un po 'di memoria, a scapito della velocità di accesso, in quanto in questo modo i dati non sarebbe stato disposto in memoria in un modo che è più efficace per l'accesso. Il compilatore normalmente sarebbe lay out la memoria in un modo che sia efficace per l'accesso e non guasterebbe troppa memoria automaticamente.

Questo approccio almeno mantenere il codice più comprensibile rispetto all'approccio spostando po avete proposto (che potrebbe o non potrebbe in realtà essere ancora simile a quello che il codice macchina compilatore genererebbe dal codice byte).

Quello che si incontra è un semplice compromesso tra le dimensioni degli oggetti dati in memoria e il costo del trattamento. Se la memoria è una preoccupazione reale, può semplicemente essere più conveniente per gettare più RAM al computer.

Ci sono alcuni casi in cui vale la pena di roba stipare in un numero intero. Lo spazio di archiviazione da solo di solito non è una buona ragione, ma se i valori stanno per essere utilizzati insieme come ad esempio una chiave per un Dizionario, un dizionario (Of Integer, a prescindere) sarà molto più veloce di un dizionario (Of SomeStructure, a prescindere).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top