Как эффективно буферизовать при записи в тысячи файлов в C ++ - PullRequest
1 голос
/ 22 января 2020

Я совершенно неопытен, когда дело доходит до операций ввода-вывода C ++, особенно при работе с буферами и т. Д. c. поэтому, пожалуйста, потерпите меня.

У меня есть программа, у которой есть вектор объектов (от 1000 до 10000). На каждом временном шаге состояние объектов обновляется. Я хочу иметь функциональность для записи полной истории времени состояния для каждого из этих объектов.

В настоящее время у меня есть функция, которая просматривает мой вектор объектов, обновляет состояние и затем вызывает функцию регистрации, которая открывается файл (ascii) для этого объекта записывает состояние в файл и закрывает файл (используя std :: ofstream). Проблема в том, что значительно замедляет мое время выполнения.

Мне рекомендовано несколько вещей, которые помогут сделать это быстрее:

  1. Буфер мой вывод для предотвращения обширных вызовов ввода / вывода на диск
  2. Запись в двоичные, не ascii файлы

Мой вопрос в основном касается 1. В частности, как бы я на самом деле это реализовал? Будет ли для каждого объекта нужен собственный буфер? или это будет один буфер, который каким-то образом знает, какой файл отправлять каждый бит данных? Если последнее, каков наилучший способ добиться этого?

Спасибо!

1 Ответ

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

Может быть, самая простая идея: вместо того, чтобы регистрировать отдельные файлы, почему бы не записать все в базу данных SQLite ?

Учитывая следующую структуру таблицы:

create table iterations (
    id integer not null,
    iteration integer not null,
    value text not null
);

В начале программы подготовьте утверждение один раз:

sqlite3_stmt *stmt;
sqlite3_prepare_v3(db, "insert into iterations values(?,?,?)", -1, SQLITE_PREPARE_PERSISTENT, &stmt, NULL);

Здесь вопросительные знаки являются заполнителями для будущих значений.

После каждой итерации симуляции вы можете пройти задайте вектор и выполните stmt несколько раз, чтобы фактически вставить строки в базу данных, например:

for (int i = 0; i < objects.size(); i++) {
    sqlite3_reset(stmt);
    // Fill in the three placeholders and execute the query.
    sqlite3_bind_int(stmt, 1, i);
    sqlite3_bind_int(stmt, 2, current_iteration); // Could be done once, but here for illustration.
    std::string state = objects[i].get_state();
    sqlite3_bind_text(stmt, 3, state.c_str(), state.size(), SQLITE_STATIC); // SQLITE_STATIC means "no need to free this"
    sqlite3_step(stmt); // Execute the query.
}

Затем можно легко запросить историю каждого отдельного объекта с помощью инструмента командной строки SQLite. или любой менеджер баз данных, который понимает SQLite.

...