brpc组件bvar源码解析(三)Variable、Reducer和Adder

6 篇文章 0 订阅
6 篇文章 0 订阅

1.Variable类

Variable是所有bvar的基类,是一个纯虚类。拥有的唯一的成员变量是_name。

Variable类中的接口分为几类:

  1. 描述相关的
    在这里插入图片描述
    子类实现纯虚函数describe,目的是将bvar的值写入ostream。

get_description不是纯虚函数,它调用了describe写入ostringstream,返回ostringstream的string。

  1. 曝光相关的
    例如:expose,expose_impl,expose_as,list_exposed,count_exposed,describe_exposed,dump_exposed等。核心是expose_impl,下文介绍。

函数expose_impl

在这里插入图片描述
函数expose_impl是实现曝光的核心逻辑。所谓“曝光”就是把bvar的地址存到一个公共的map中,以便后续可以遍历和查询到。

具体的做法是:
(1)根据prefix+name生成统一格式的曝光名称_name:非字母、非数字的全部转成下划线
(2)根据(1)生成的曝光名称_name查询所属的VarMapWithLock:
首先对_name进行了简单的hash,然后对VarMapWithLock数组s_var_maps的长度SUB_MAP_COUNT取模得到i,返回s_var_maps的第i个成员。这里这么做的目的是为了减少VarMapWithLock中的锁竞争的频率。
在这里插入图片描述

(3)根据_name查询VarMapWithLock中是否存在key为_name的记录
VarMapWithLock其实就是加了锁的hashmap。
在这里插入图片描述

如果查不到,则插入pair<name, VarEntry>,VarEntry的var变量赋值this值,display_filter变量赋值入参display_filter。
在这里插入图片描述
display_filter是枚举类型DisplayFilter,表示显示到文本中、html中还是全部。list_exposed函数会将入参和所有VarEntry的display_filter进行与操作,只输出满足条件的bvar。
在这里插入图片描述

(4)如果(3)能查到记录,说明有同名bar已经进行了曝光,则根据gflags进行相关处理(直接abort或者打印error log)

函数hide

在这里插入图片描述
很容易理解,就是根据_name从对应的VarMapWithLock中删除记录。

函数list_exposed

在这里插入图片描述
在这里插入图片描述

遍历所有曝光的bvar,即遍历s_var_maps中的所有map的所有pair,选出满足display_filter条件的bvar的name保存到names数组中。

遍历s_var_maps中的每个map时,首先都需要先加锁,才能遍历map中的每个pair。为了防止个数太多、加锁时间过长,遍历每超过一定个数(256个),都主动释放一下锁。

函数describe_exposed

在这里插入图片描述
即根据name从s_var_maps查询到VarEntry*,调用该bvar的describe函数,结果保存到os中。

函数dump_exposed

在这里插入图片描述
查询所有曝光的bvar,将符合options中的通配符white_wildcards和black_wildcards条件的bvar都调用dumper->dump函数。例如white_wildcards = “foo_bar_*”; black_wildcards = “*var5”。函数返回值是dump的bvar的个数。

如果通配符white_wildcards是空的,那么先通过list_exposed得到所有曝光的bvar的name,然后对name进行排序,遍历name数组,对于符合通配符条件的name,调用describe_exposed函数将该bvar的描述保存到ostream,然后调用dumper->dump函数,传入name和保存描述的ostream转成的字符串。

Dumper是一个纯虚类,由开发者自己继承实现。
在这里插入图片描述

2.Reducer类

Reducer类定义:
在这里插入图片描述
3个模板类型:
T:bvar保存的值的类型
Op:“累加”的op
InvOp:与“累加”相反操作的OP,默认是VoidOp即无具体操作;这个介绍采样的时候再具体介绍。

成员变量:
在这里插入图片描述
构造函数:
在这里插入图片描述
add_cr_non_integral是如果T不是整型则增加const&修饰。
identity赋值T的默认构造函数生成的对象,如果T是POD类型,则T()就是0值。

_combiner:AgentCombiner<T, T, Op>类的对象;AgentCombiner的第1、第2模板参数都是T,说明它的结果类型和元素类型是相同的、都是T(介绍AgentCombiner时说过这2个类型可以不同)
_sampler:ReducerSampler<Reducer, T, Op, InvOp>类型的指针,此处设置为NULL,只有当前bvar有采样需要,即成员函数get_sampler被调用时_sampler才会被new出来。
_series_sampler:嵌套类SeriesSampler类型的指针,此处设置为NULL,后面介绍采样时再介绍。
_inv_op:InvOp类的对象。

Op类的对象在_combiner中有保存,所以不需要重复保存;

函数operator<<

在这里插入图片描述
函数operator<<是对bvar增加值时调用的,例如

bvar::Adder<int> sum;
sum << 1 << 2 << 3 << 4;
LOG(INFO) << sum.get_value(); // 10

具体实现是:
(1)调用_combiner的get_or_create_tls_agent函数,获得此bvar在当前线程tls数据中存储的agent的地址;
(2)然后调用agent->element.modify,传入Op对象和入参value,内部通过call_op_returning_void调用Op对象的函数operator()实现element当前值与入参value的“累加”、并将新值保存到agent->element。
在这里插入图片描述
(3)返回当前对象的引用,以便实现连续操作;
(4)这个函数调用栈完全没有锁,所以即使bvar在不同线程调用性能也很高。

函数get_value

在这里插入图片描述
这个函数目的是获得bvar的最新值,那么就要把在各个线程tls存储的agent的值进行“累加”。
实现上由于_combiner.combine_agents已经封装好了这个功能,所以直接调用并返回即可。

_combiner.combine_agents调用栈底部有加锁操作,所以应该尽量少调用。

函数describe

在这里插入图片描述
调用get_value获得最新值保存到os中,如果T为string类型并且quote_string为true,则前后加上引号。

函数expose_impl

在这里插入图片描述

这里override了基类虚函数Variable::expose_impl。主要是调用了Variable::expose_impl进行了实际的曝光操作,然后根据条件和参数初始化了_series_sampler(这个后面介绍采样时再介绍)。

3.Adder类

在这里插入图片描述
在这里插入图片描述
由于父类Reducer该实现的都实现了,所以Adder定义就比较简洁了。重点就是传3个模板参数,一个是值类型T,一个是“累加”Op:AddTo类,一个是“逆反”Op:MinusFrom类。

Op有一个注意点是:必须把新值保存到第一个参数lhs中,而不是返回。

(待续)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值