Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为实时操作配置SQLite_C++_Sqlite_Optimization_Real Time - Fatal编程技术网

C++ 为实时操作配置SQLite

C++ 为实时操作配置SQLite,c++,sqlite,optimization,real-time,C++,Sqlite,Optimization,Real Time,简而言之,这篇文章想回答以下问题:我们如何(如果可能的话)配置SQLite数据库以确保任何INSERT命令都能在8毫秒内返回 所谓配置,我的意思是:编译选项、数据库pragma选项和运行时选项 为了提供一些背景信息,我们希望以120 fps的速度应用相同的INSERT语句。(1000毫秒/120帧)≃ 8毫秒) 使用以下字符串创建数据库: "CREATE TABLE IF NOT EXISTS MYTABLE (" "int1 INTEGER PRIMARY KEY AUTOINCR

简而言之,这篇文章想回答以下问题:我们如何(如果可能的话)配置SQLite数据库以确保任何INSERT命令都能在8毫秒内返回

所谓配置,我的意思是:编译选项、数据库pragma选项和运行时选项

为了提供一些背景信息,我们希望以120 fps的速度应用相同的INSERT语句。(1000毫秒/120帧)≃ 8毫秒)

使用以下字符串创建数据库:

"CREATE TABLE IF NOT EXISTS MYTABLE ("
      "int1 INTEGER PRIMARY KEY AUTOINCREMENT, "
      "int2 INTEGER, "
      "int3 INTEGER, "
      "int4 INTEGER, "
      "fileName TEXT);
以及选择:

"PRAGMA SYNCHRONOUS=NORMAL;"
"PRAGMA JOURNAL_MODE=WAL;"
INSERT语句如下所示:

INSERT INTO MYTABLE VALUES (NULL, ?, ?, ?, ?)
最后一个?(对于fileName)是文件名,因此它是一个小字符串。因此,每个插件都很小

当然,我使用预编译语句来加速这个过程

我有一个小程序,每8毫秒插入一次,并测量执行此插入所需的时间。更准确地说,程序先进行一次插入,然后等待8毫秒,然后再进行另一次插入,等等。。。最后,推送了7200个插入,因此程序运行了大约1分钟

以下是显示两个图表的两个链接:

此图显示了根据时间(以分钟表示)进行插入所花费的毫秒数。如您所见,大多数情况下,插入时间为0,但也有超过100毫秒的尖峰

此图像是相同数据的直方图表示。5毫秒以下的所有值都没有表示出来,但我可以告诉您,从7200次插入中,7161次插入的值低于5毫秒(并且会在0处出现一个巨大的峰值,这会降低图表的可读性)

总节目时间为 实1m2.286s 用户0m1.228s sys 0m0.320s

假设是1分4秒。不要忘记,我们花了7200次8毫秒等待。因此7200次插入需要4秒--->我们有每秒1800次插入的速率,因此每次插入的平均时间为0.55毫秒。 这真的很好,除了在我的例子中,我希望所有的插入都在8毫秒以下,图表显示情况显然不是这样

那么这些山峰是从哪里来的呢

当WAL文件达到给定大小(在我们的例子中为1MB)时,SQLite会创建一个检查点(WAL文件应用于实际的数据库文件)。因为我们传递了PRAGMA SYNCHRONOUS=NORMAL,所以此时,SQLite在硬盘上执行fsync。 我们假设这个fsync使得相应的插入非常慢。 插入时间过长并不取决于WAL文件的大小。我们使用了链接到WAL文件的pragma WAL_自动检查点(默认为1000),无法降低山峰的高度

我们还尝试使用PRAGMA SYNCHRONOUS=OFF。表演更好,但仍然不够。 作为参考,我的计算机上的脏页背景比率(/proc/sys/vm/dirty\u background\u ratio)设置为0,这意味着缓存中的所有脏页必须立即刷新硬盘驱动器


是否有人知道如何“平滑”图表,即所有插入时间不会超过8毫秒?

默认情况下,SQLite中的几乎所有内容都是针对吞吐量而不是延迟进行优化的

WAL模式将大多数延迟移动到检查点,但如果您不希望这些大延迟,则必须使用更频繁的检查点,即在每个事务之后执行检查点。 在这种情况下,WAL模式没有意义;最好试试
journal\u mode=persist
。 (这不会有多大帮助,因为延迟主要来自同步,而不是数据量。)


如果WAL/journal操作太慢,并且即使
synchronous=off
也不够快,那么您唯一的选择就是禁用事务安全并尝试
journal\u mode=memory
甚至
=off

为什么需要这样的计时?从工作过RS485通信需要40毫秒时间片的系统的角度来看,我认为你不会在非实时操作系统上实现这一点。您使用的是什么操作系统?一般来说,我不喜欢多线程,但在这种情况下,INSERT语句的执行应该在一个单独的线程中,两个线程安全地共享要插入的记录的std::deque。@Steger:这正是我们在上述项目中所做的,并赋予了快速线程实时优先级,但我们始终无法达到预期的时间。不过,我们已经达到了“足够好”的程度。你可以试试这些优化。