如何在C++中写入 1000 个文件时有效地缓冲

How to buffer efficiently when writing to 1000s of files in C++

本文关键字:文件 有效地 缓冲 1000 C++      更新时间:2023-10-16

我在C++ I/O 操作方面非常缺乏经验,尤其是在处理缓冲区等时,所以请耐心等待。

我有一个程序,它有一个对象向量(1000 - 10,000s(。在每个时间步长,对象的状态都会更新。我希望能够为每个对象记录完整的状态时间历史记录。

目前,我有一个函数,它循环遍历我的对象向量,更新状态,然后调用一个日志记录函数,该函数打开该对象的文件 (ascii(,将状态写入文件,然后关闭文件(使用 std::ofstream(。问题是这大大减慢了我的运行时间。

我被推荐了几件事来帮助加快速度:

  1. 缓冲我的输出以防止对磁盘进行大量 I/O 调用
  2. 写入二进制文件而不是 ASCII 文件

我的问题主要涉及 1.具体来说,我将如何实际实现这一点?每个对象是否实际上都需要自己的缓冲区?或者这会是一个缓冲区,以某种方式知道要发送每个数据位的文件?如果是后者,实现这一目标的最佳方法是什么?

谢谢!

也许最简单的想法是:与其记录到单独的文件,为什么不将所有内容记录到 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 的数据库管理器轻松查询每个对象的历史记录。