Производительность в отношении «получения» структурных данных

0

У меня возникает вопрос о эффектах производительности при учете двух возможных методов "получения" данных из данной структуры. Предполагается, что переменная "name" относится к значению "id".

Предполагая, что у меня есть структура и перечисление следующим образом,

enum GenericId { NONE, ONE, TWO };

struct GenericTypeDefinition {
    GenericId id;
    const char name[8];
    ...
};

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

Теперь вот где мой вопрос о производительности становится актуальным. Скажем, мне нужно создать сотни таких экземпляров, все из которых будут заблокированы для определенного количества имен и уникального идентификатора. Эти экземпляры будут называться набором возможных "GenericTypeDefinition" во всей программе. Помните, что значение "имя" относится к значению "id". Мой вопрос: смогу ли я сохранить некоторую память, если бы я реализовал функцию вроде next (и удалил переменную имени из структуры),

struct GenericTypeDefinition { // 'name' is now removed.
    GenericId id;
    ...
};

const char* Definition_ToString(GenericEnum e) {
    switch (e) {
        case NONE: return "Nothing";
        case ZERO: return "Zero is not nothing.";
    ...
}

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

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

Теги:
performance

4 ответа

1
Лучший ответ

Если я понимаю, что вы спрашиваете, вы добавляете избыточные данные в свою структуру. По сути, вы можете получить имя структуры из идентификатора в структуре. Но вы также можете сохранить имя непосредственно в структуре.

Итак, вы правы - не запоминание имени сохранит память, потому что вы не сохраните имя с каждым элементом. Стоимость - это немного времени. Вам нужно будет вызвать функцию, чтобы дать вам имя из идентификатора каждый раз, когда вам это нужно. Вам придется взвесить эти компромиссы, чтобы определить, что более важно.

  • 0
    Спасибо за ваш ответ, я ценю это.
1

Дьявол в деталях. Ответ зависит от многих вещей. Например, как часто распределяется такая структура, как часто она используется и как часто char name[8]; используется.

Если вы удалите name из структуры, может произойти несколько сценариев:

  • если у вас много объектов такого типа и хороший распределитель, вы сэкономите место.
  • если вы используете эти объекты широко в течение некоторого исчисления, и время от времени вы используете name, вы сэкономите время, благодаря лучшей производительности кеша.
  • если вы широко используете name для некоторых вычислений, а ваша функция Definition_ToString немного сложнее, чем в вашем примере, вы потеряете производительность.

Однако, по моей оценке, такие оптимизации могут ускорить программу только с помощью небольшого фактора. Это может помочь в случаях, когда вы считаете в микросекундах. Если ваша программа отчаянно медленна, найдите асимптотически лучший алгоритм.

0

В большинстве случаев компилятор будет выполнять эту работу за вас. Он обычно хранит все строковые литералы const в разделе RO исполняемого файла. В зависимости от уровня оптимизации он может даже избавиться от памяти, занятой массивом char в структуре. Таким образом, ваш исполняемый размер будет расти, но это не повлияет на память времени выполнения. Однако, поскольку имя привязано к идентификатору, логически имеет смысл реализовать вторую версию, поэтому в будущем, если вы хотите добавить новый идентификатор, вам не нужно делать лишнюю работу.

0

В вашем первом случае задача инициализации структур с правильным идентификатором и NAME означает, что программа в самом начале будет копировать литералы, это строки (потому что я предполагаю, что вы инициализируете структуры со строками в пределах кода) в другое пространство в ОЗУ, на которое указывает char [].

Вместо этого второй случай означает, что значение считывается из самой программы (литералы жестко закодированы в таблице где-то в глубоком коде ассемблера) и вернет указатель на нее (исправьте меня, если указатель не находится где-то в программа, но возвращаемый const char * сохраняется как переменная), поэтому вы сохраняете некоторую память.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню