Если у меня есть три отдельных значения, которые все могли вписаться на 32 битах, имеет ли смысл использовать UINT для их хранения?

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

Вопрос

Что я имею в виду, скажем, у меня есть struct представлять некоторые данные, и это выглядит так:

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

А. short и два byte Значения все могут вписаться на 32 бита. Что мне интересно, это (для целей выравнивания, производительность, что угодно), если бы на самом деле вместо этого будет иметь смысл хранить эти данные в следующем формате:

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

Это бессмысленно? Что было бы преимуществами / недостатками?

Это было полезно?

Решение

В .NET, когда вы собираетесь использовать struct Во всяком случае, вы также можете украсить структуру с StructLayoutAttribute так:

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

Это будет иметь эффект, что поля выложены последовательно, например, поле B начнется в смещении 16.

Значение 1 для Pack означает, что поля выровнены на byte границы.

Другие советы

Вам следует учитывать только втягивание нескольких значений в UINT, если значения тесно связаны друг с другом, обычно передаются вместе, и никогда не или очень редко изменяются независимо друг от друга. Стоимость распаковки и переупаковки UINT, чтобы изменить его значение, делает это очень дорогим (в раз размере кода и время выполнения) по сравнению с сохранением трех байтов отдельно.

При выполнении Microdevice с общей суммой 10K байтов ОЗУ, упаковка, как это может стоить того, потому что память более ценно, чем скорость исполнения. На нормальном настольном ПК или даже на мобильном устройстве мобильного телефона эта упаковка, вероятно, не стоит усилий.

Вы можете остаться с вашим определением структуры и применить Structlayout. атрибут с AN Structlayoutattribute.pack. Значение 1. Но на самом деле, вы, вероятно, сэкономьте немного памяти за счет скорости доступа, так как таким образом данные не будут выложены в памяти таким образом, чтобы наиболее эффективным для доступа. Компилятор обычно выложит память таким образом, чтобы это было эффективно для доступа и автоматически испортить слишком много памяти.

Этот подход, по крайней мере, сохранит ваш код более понятным, чем предложенный вами подход бита (который может или, на самом деле, все равно будет похоже на то, что компилятор машинного кода будет генерировать из байтового кода).

То, что вы столкнетесь, - это простое компромисс между размерами объектов данных в памяти и стоимость обработки. Если память является реальной проблемой, может быть просто дешевле бросить больше оперативной памяти на вашу машину.

Есть несколько случаев, когда стоит до целого числа. Только место для хранения, как правило, не очень хорошая причина, но если значения будут использоваться вместе, например, например, ключ для словаря, словарь (целое число, что угодно) будет намного быстрее, чем словарь (из-за сомнения, что угодно).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top