sysrepo running 数据库缓存机制分析

[!note]
本篇文档的所有分析过程均基于如下软件版本:

  • sysrepo v2.2.60

概要

本文主要分析 sysrepo 函数 sr_connect 参数 const sr_conn_options_t opts 选用 SR_CONN_CACHE_RUNNING 表现差异。

该选项的说明如下:

Always cache running datastore data which makes mainly repeated retrieval
of data much faster. Affects all sessions created on this connection.

可以看到这是一个关于缓存机制的选项,主要作用是缓存 running 数据库中的一些数据,以便在重复获取时加快获取速度。

机制分析

更新机制

追溯 SR_CONN_CACHE_RUNNING 的使用位置,主要是用于 sr_modinfo_data_load,该函数的作用是:“Load data for modules in mod info.”。而该函数的唯一调用者是 sr_modinfo_consolidate,其作用是“Consolidate mod info by adding dependencies of the added modules, check the permissions, lock, and load data.”

分析 sr_modinfo_consolidate 的参数,与缓存相关的主要有如下几个:

参数类型说明
mod_infostruct sr_mod_info_s *需要处理的模块集合
mi_optsint控制是否可以使用缓存(如果缓存存在)。判断依据:

mi_opts & SR_MI_DATA_CACHE

使用该标志的调用者主要是从 sysrepo 中获取现有数据

其中,mod_info 主要由 sr_modinfo_collect_xpath 构建,其大致流程如下:

  1. 首先 调用 lys_find_xpath_atoms 分析传入的 xpath,结合 ly_ctx 内容,获取需要处理的模块集合(set of yang modules)
  2. 将需要处理的模块集合保存到 mod_info 内,即一个 mod_info 保存了多个 yang modules 及额外的信息

来到 sr_modinfo_data_load,其关于缓存处理的主要流程如下:

  1. 首先判断各参数是否满足使用缓存的条件,如果不满足则不走缓存逻辑
  2. 如果 mod_info 满足缓存条件,则 调用 sr_conn_run_cache_update 尝试更新缓存:
    1. 遍历 mod_info 中的 yang module
      1. 检查 sysrepo connection 中是否存在缓存
      2. 如果 不存在,则创建关于此模块的新缓存
      3. 如果 缓存已过期(时间戳比最后一次更新的时间戳早),则更新缓存内容。缓存内容为该 yang module 的 data
  3. 如果 需要获取的是 runnning 数据库的内容,则直接返回缓存作为 mod_info 的数据

作用范围

从上一个章节可以看到,使用缓存需要满足下面的条件:

  1. 从 sysrepo 中获取数据时
  2. 从 running 数据库中获取数据时

这也即是该缓存机制的作用范围。

加速效果

文件 tests/perf.c 中的测试项 get tree hash 和 get tree hash cached 分别测试了不适用缓存与使用缓存情况下从 running 数据库获取数据的性能表现。

上述性能测试的测试方法如下:

  1. 获取两个参数,参数一 count 为数据量,参数二 tiers 为循环次数,最终结果为时间总开销除以循环次数
  2. 创建 sysrepo session 并插入 count 对应量的数据
  3. 从 session 中获取数据里面的某一个数据,数据的 key=count/2,即取的是列表中间的元素

编译该测试用例的方法如下:

mkdir build && cd build
cmake -DENABLE_PERF_TESTS=on ..
make -j`nproc`

在我的环境下,运行该性能测试的结果如下:

$ ./tests/sr_perf 100000 10sr_perf:data set size: 100000each test executed: 10 times| get tree ........................ |   0.659725 s |
| get item ........................ |   0.611825 s |
| get tree hash ................... |   0.441830 s |
| get tree hash cached ............ |   0.029272 s |
| edit item create ................ |   8.695930 s |
| edit batch create ............... |   8.133344 s |
| oper get tree ................... |   1.003623 s |

可以看到,获取同样的数据信息,使用缓存只需要不使用缓存时不到 10% 的时间,相当于十余倍的性能差距,足以可以说明这个缓存是相当有作用的。