使用 Sqlite3 blob 的 C++ 程序中的 RAM 消耗
RAM consumption inside a C++ program using Sqlite3 blob
我在 C++ 程序中使用 sqlite3 dbms,主要用于将文件存储为 blob 对象(我知道这不是最佳选择)。
显然我是逐步编写它们的,因为它们有时可能很大(40-80MB),为此我必须首先使用绑定函数 sqlite3_bind_zeroblob(...)
创建 blob 的占位符,然后我打开blob 以增量方式写入和读取。
我面临的问题是,当我创建 blob 占位符时(在 sqlite3_step
期间),我的应用程序的 RAM 消耗达到 80-160MB 并持续 2-3 秒,一旦创建了 RAM消耗最多回到 2-3MB。
我不明白为什么!如果他们创建了一种增量写入 blob 的方法,那么肯定有一种方法可以在不浪费 160MB RAM 的情况下创建那个愚蠢的占位符,但我没有找到它。你有什么建议吗?
sqlite3_stmt* stm = NULL;
sqlite3_blob *BLOB = NULL;
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stm, NULL);
rc = sqlite3_bind_blob(stm, 1, wpath.c_str(), wpath.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_text(stm, 2, hash.c_str(), hash.size(), SQLITE_STATIC);
rc = sqlite3_bind_zeroblob(stm, 3, size);
rc = sqlite3_bind_int(stm, 4, versione);
rc = sqlite3_bind_blob(stm, 5, last.c_str(), last.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_step(stm);
if (rc != SQLITE_DONE) {
fprintf(stderr, " This file was already present in the database!\n", rc);
return;
}
else {
fprintf(stdout, "Record FILE created successfully\n");
}
这是一个已报告的问题 HERE。
而官方的回答是:
In order for zeroblobs to work as above (using a fixed amount of
memory no matter how big they are) all zeroblobs must be at the end
of the row. In other words, the columns of the table that are
receiving the zeroblobs must be the last columns in the table. If
any non-zero content follows the zeroblob, then the zeroblob is
expanded into a literal sequence of zero bytes, meaning memory must
be allocated for the entire zeroblob.
因此您需要更改顺序来修复它:
sqlite3_stmt* stm = NULL;
sqlite3_blob *BLOB = NULL;
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stm, NULL);
rc = sqlite3_bind_blob(stm, 1, wpath.c_str(), wpath.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_text(stm, 2, hash.c_str(), hash.size(), SQLITE_STATIC);
rc = sqlite3_bind_int(stm, 3, versione);
rc = sqlite3_bind_blob(stm, 4, last.c_str(), last.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_zeroblob(stm, 5, size);
rc = sqlite3_step(stm);
if (rc != SQLITE_DONE) {
fprintf(stderr, " This file was already present in the database!\n", rc);
return;
}
else {
fprintf(stdout, "Record FILE created successfully\n");
}
我在 C++ 程序中使用 sqlite3 dbms,主要用于将文件存储为 blob 对象(我知道这不是最佳选择)。
显然我是逐步编写它们的,因为它们有时可能很大(40-80MB),为此我必须首先使用绑定函数 sqlite3_bind_zeroblob(...)
创建 blob 的占位符,然后我打开blob 以增量方式写入和读取。
我面临的问题是,当我创建 blob 占位符时(在 sqlite3_step
期间),我的应用程序的 RAM 消耗达到 80-160MB 并持续 2-3 秒,一旦创建了 RAM消耗最多回到 2-3MB。
我不明白为什么!如果他们创建了一种增量写入 blob 的方法,那么肯定有一种方法可以在不浪费 160MB RAM 的情况下创建那个愚蠢的占位符,但我没有找到它。你有什么建议吗?
sqlite3_stmt* stm = NULL;
sqlite3_blob *BLOB = NULL;
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stm, NULL);
rc = sqlite3_bind_blob(stm, 1, wpath.c_str(), wpath.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_text(stm, 2, hash.c_str(), hash.size(), SQLITE_STATIC);
rc = sqlite3_bind_zeroblob(stm, 3, size);
rc = sqlite3_bind_int(stm, 4, versione);
rc = sqlite3_bind_blob(stm, 5, last.c_str(), last.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_step(stm);
if (rc != SQLITE_DONE) {
fprintf(stderr, " This file was already present in the database!\n", rc);
return;
}
else {
fprintf(stdout, "Record FILE created successfully\n");
}
这是一个已报告的问题 HERE。
而官方的回答是:
In order for zeroblobs to work as above (using a fixed amount of memory no matter how big they are) all zeroblobs must be at the end of the row. In other words, the columns of the table that are receiving the zeroblobs must be the last columns in the table. If any non-zero content follows the zeroblob, then the zeroblob is expanded into a literal sequence of zero bytes, meaning memory must be allocated for the entire zeroblob.
因此您需要更改顺序来修复它:
sqlite3_stmt* stm = NULL;
sqlite3_blob *BLOB = NULL;
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stm, NULL);
rc = sqlite3_bind_blob(stm, 1, wpath.c_str(), wpath.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_text(stm, 2, hash.c_str(), hash.size(), SQLITE_STATIC);
rc = sqlite3_bind_int(stm, 3, versione);
rc = sqlite3_bind_blob(stm, 4, last.c_str(), last.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_zeroblob(stm, 5, size);
rc = sqlite3_step(stm);
if (rc != SQLITE_DONE) {
fprintf(stderr, " This file was already present in the database!\n", rc);
return;
}
else {
fprintf(stdout, "Record FILE created successfully\n");
}