Dynami c многомерный массив с ключом в C ++ - PullRequest
0 голосов
/ 14 января 2020

Я пытаюсь найти хороший способ обработки сценария ниже в C ++.

Когда мы запускаем службу на сервере, таблица параметров, подобная приведенной ниже, будет инициализирована на основе данных в базе данных.

ID, filed_1, field_2, .... , field 50
100abc, ***, ***, ...., ***
120def, ***, ***, ...., ***
...
...
500xyz, ***, ***, ..., ***

Поля / столбцы : около 50. Количество и формат полей фиксированы. Все типы полей: int, double или char * (не очень long char *).

Записи / строки : максимум 200. Исходя из данных, количество записей будет отличаться каждый раз.

Идентификатор уникален.

Во время расчета таблица параметров будет считываться и обновляться 500 раз в секунду. (поиск по идентификатору и имени поля, я полагаю)

Низкая задержка важна для системы.

Какую структуру данных лучше всего использовать в таком сценарии?

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

Большое спасибо.

1 Ответ

0 голосов
/ 14 января 2020

К вашему сведению, вы задаете самоуверенный вопрос об алгоритмах и структурах данных, который обычно лучше подходит для этого сайта обмена стека: https://softwareengineering.stackexchange.com/

В любом случае, со всеми соответствующими зерна соли, вот мое неосведомленное мнение. Учитывая это:

Количество и формат полей фиксированы.

и это:

В системе важна низкая задержка.

Рассмотрите возможность использования карты ha sh с идеальным хешированием Функция поиска ваших полей по имени. В те дни вы использовали gperf в качестве шага сборки для генерации хеш-функции в C, но с C ++ constexpr magi c у вас есть эта опция:

https://github.com/Kronuz/constexpr-phf

Документация там просто так, так бесполезно, вот как вы ее используете. Начните с ввода полей, чтобы сделать функцию ha sh:

fnv1ah32 fnv1a{};
constexpr auto fields_phf = phf::make_phf({
    fnv1a("field1"), 
    fnv1a("field2"), 
    fnv1a("field3"), 
    fnv1a("field4")
    /* , ... */
});

У меня нет особого понимания того, что использовать для значений, но так как вы хотите сохранить один из 3 типов, я Для этого примера будем использовать std::variant:

// ...assuming your field values will fit in std::string's short string optimization
using Value = std::variant<int, double, std::string>;

Затем вы можете обернуть таблицу поиска O (1) вокруг непрерывного массива данных:

struct Row {
    std::array<Value, FIELD_COUNT> fields;

    template <typename T>
    Value& operator [](T&& t) { 
        auto pos = fields_phf.find(fnv1a(t));
        if (pos == phf::npos) {
            throw std::runtime_error("unknown field");
        }
        return fields[pos];
    }
};

Затем используйте обычную ha sh таблица для поиска ваших строк, что является довольно хорошим значением по умолчанию, если вы не знаете значений заранее. Зарезервируйте 200 строк, чтобы свести к минимуму перефразирование, так как вы думаете, что это ваш потолок:

std::unordered_map<std::string, Row> table;
table.reserve(200);

Затем вы можете сделать поиск:

int main() {
table["row1"]["field1"] = 42;
table["row2"]["field2"] = "hello";

Демо: https://godbolt.org/z/z8euVY

...