В моей программе есть простая функция:
enum {
TABLE_INDEX_TYPE_UINT8 = 0,
TABLE_INDEX_TYPE_UINT16,
TABLE_INDEX_TYPE_UINT32,
};
// inline method
uint8_t MyTable :: GetTableIndexTypeForTableSize(uint32_t tableSize) const
{
// Deliberately testing for strictly-less-than-255/65535 here,
// because 255 and 65535 are used as special sentinel values
return (tableSize < 255) ? TABLE_INDEX_TYPE_UINT8
: ((tableSize < 65535) ? TABLE_INDEX_TYPE_UINT16 : TABLE_INDEX_TYPE_UINT32);
}
В текущей версии моей программы я вызываю этот метод всякий раз, когда tableSize
изменяется, и сохраняю результат в переменной-члене для быстрого повторного использования, и это прекрасно работает.
Однако сегодня я экспериментирую с уменьшением sizeof(MyTable)
, и один из способов сделать это - избавиться от ненужных переменных-членов. Поскольку кэшированный результат вышеприведенной функции всегда можно повторно вычислить (основываясь на текущем значении переменной-члена tableSize
), я изменил код так, чтобы он просто вызывал GetTableIndexTypeForTableSize(tableSize)
всякий раз, когда это необходимо.
Это также хорошо работает (и позволяет мне уменьшить sizeof(MyTable)
на 4 байта, ага), но это приводит к ощутимому (~ 5%) снижению производительности в моем тесте производительности - я считаю, что это потому, что текущая реализация GetTableIndexForTableSize()
включает две операции ветвления.
Итак, мой вопрос: есть ли умный способ переопределить вышеуказанную функцию, чтобы она не требовала какого-либо ветвления, и таким образом избежать замедления на 5%? (Я предполагаю, что использование таблицы поиска будет
плохая идея, так как я бы заменил задержки из-за неправильного предсказания ветвлений задержками доступа к ОЗУ, что еще больше замедлило бы работу *