brpc源码解析(十二)—— 核心组件bvar详解(3)AgentGroup类详解

上一篇从Reduce和Adder切人整体介绍了下bvar的实现机制,提到了combiner和agent,其中agent负责tls数据的管理和分配,也是bvar最核心的基本机制之一,本篇文章会根据源码介绍下agent的机制。AgentGroup类负责各个agent的分配和管理,采用了块存储。

1. 类基本定义

AgentGroup定义如下:
在这里插入图片描述
类名是AgentGroup,之所以叫group是因为同类型的tls数据会统一管理,模板参数是Agent,使用上传入的是AgentCombiner::Agent包装下的实际类型,比如bvar::Adder value1和bvar::Adder value2所用的会是相同实例化的类,会共用同一个tls存储数组变量。看代码的注释,brpc后续有计划让不同类型的变量也共用一个agentgroup。

类外定义了AgentId,其实就是个int,用来标识变量、在存储块中定位变量位置的,下面会详细介绍。

2. 成员变量

首先是有两个const static的关于每个block存多少个元素的变量,RAW_BLOCK_SIZE和ELEMENTS_PER_BLOCK,根据赋值我们可以知道,如果Agent类型大于等于4096,那么每个块就一个元素,再比如如果Agent类型占1024,那么每块的元素会是4个。
在这里插入图片描述
另外还有四个static变量,因为是static变量模板参数相同的实例都会共用。
在这里插入图片描述
(1)_s_mutex是新建和销毁agent要用到的锁。
(2)_s_agent_kinds是当前agentgroup(Agent参数相同)的agent数量,同时也用于构造agentId。
(3)_s_free_ids是个deque的指针,保存了空闲的agentId用于再分配。
(4)_s_tls_blocks由__thread修饰,tls变量,是个vector的指针,这个vector保存的则是ThreadBlock的指针,这也是agent的核心变量,指向每个thread的tls数据块。
在这里插入图片描述
ThreadBlock是内部struct,则是真正的tls存储类型,由ELEMENTS_PER_BLOCK大小的数组_agents和一个取指定偏移量位置变量的at函数组成,用BAIDU_CACHELINE_ALIGNMENT修饰是为了对齐cache line避免cache bouncing。

3. 函数

3.1 Private函数

Private函数有两个,都比较简单,如下:
(1)static void _destroy_tls_blocks()
析构_s_tls_blocks里的元素并delete _s_tls_blocks本身,用于线程退出的时候清除tls存储。
在这里插入图片描述

(2)inline static std::deque &_get_free_ids()
获取空闲的已有id,用deque保存我理解是因为它resize比较高效。
在这里插入图片描述

3.1 Public的函数

public函数主要是供combiner调用,如下:
(1)inline static AgentId create_new_agent()
在这里插入图片描述
根据名称就知道,这是新建agent的,返回的是新建agent的id,这个函数由combiner的构造函数调用,这个函数比较简单,就是加锁后先判断是否有空闲的id(包括原来分配的tls存储),有就直接返回老的,否则返回_s_agent_kinds的值并对_s_agent_kinds自增,也就是新建了一个id,这里说的新建仅仅是新建id,并没有分配空间构造变量,如果是已有的id则是原来已经构造好的。

(2)inline static int destroy_agent(AgentId id)
在这里插入图片描述
销毁agent,这里说的销毁也可以理解成归还,并没有delete建立的对象,后续还可以重用,combiner的析构函数会调用,比如一个bvar析构了,对应的combiner析构了也就会归还agentid。

(3)inline static Agent* get_tls_agent(AgentId id)
在这里插入图片描述
根据id拿到agent指针,如果block还没分配直接返回NULL,id除以perlock得到block_id(定位到block),再根据块内偏移id-blockid*elements_per_block定位到具体数据,注意注释里描述的,不存在的id可能返回非null,是因为id和对应的数据是可以重用的,比如id=10的归还了,但因为10所指向的数据块还在,这个时候用如果用10来取仍然能取到,不过实际使用中没啥影响。

(4)inline static Agent* get_or_create_tls_agent(AgentId id)
在这里插入图片描述
和get_tls_agent类似,根据id拿到agent指针,但如果block还没分配会进行分配,之所以分成了两个函数是为了让get_tls_agent的部分实现尽可能的快。Combiner在调用的时候会先调AgentGroup::get_tls_agent(_id),如果为null再调AgentGroup::get_or_create_tls_agent(_id)。容易理解实际使用中get_tls_agent就能返回非NULL的占比很大。和get_tls_agent的主要区别在于多了_s_tls_blocks为null和(*_s_tls_blocks)[block_id]为null的时候的空间分配,也就是or_create的含义。注意中间的butil::thread_atexit(_destroy_tls_blocks),线程退出的时候调用上面说的private的_destroy_tls_blocks函数。

4. 总结

AgentGroup负责tls数据的分配和获取,相同类型的会共用一个块存储数组,设计宗旨是能够让调用方尽可能快地获取到某个bvar变量的agent。后面将会解析combiner源码,会进一步介绍combiner是如何使用AgentGroup的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ansible是一种自动化运维工具,它可以自动化部署、配置和管理多台服务器。下面是Ansible的安装步骤和核心组件详解: 一、Ansible的安装 1.安装依赖包 在CentOS/RHEL上安装Ansible之前,需要安装一些必要的依赖包: ``` yum install epel-release -y yum install python-pip python-devel -y yum install gcc -y ``` 2.安装Ansible 使用pip安装Ansible: ``` pip install ansible ``` 3.验证安装 安装完成后,可以使用以下命令验证Ansible是否安装成功: ``` ansible --version ``` 二、Ansible的核心组件 1.Inventory Inventory是Ansible的主机清单文件,它用于定义目标主机或主机组,以便Ansible可以执行任务。Inventory可以使用INI格式或YAML格式编写。 以下是一个Inventory的示例: ``` [web] 192.168.1.100 192.168.1.101 [db] 192.168.1.102 ``` 上面的Inventory定义了两个主机组,web和db。web组包含了两个主机:192.168.1.100和192.168.1.101,而db组只包含一个主机:192.168.1.102。 2.Playbook Playbook是Ansible的任务剧本文件,它用于定义一系列任务和执行顺序。Playbook使用YAML格式编写。 以下是一个Playbook的示例: ``` - name: Install Apache hosts: web become: true tasks: - name: Install Apache package yum: name: httpd state: present - name: Start Apache service service: name: httpd state: started ``` 上面的Playbook定义了一个名为Install Apache的任务,在web组中安装Apache,然后启动Apache服务。 3.Module Module是Ansible的模块,它用于执行特定的任务。Ansible有很多内置的模块,如yum、copy、service等。 以下是一些常用的模块: - yum:安装或卸载软件包; - copy:复制文件; - service:管理服务; - user:管理用户; - file:管理文件和目录; - shell:在目标主机上执行Shell命令。 4.Role Role是Ansible的角色,它用于组织Playbook中的任务。Role可以包含多个任务、变量和模板。 以下是一个Role的示例: ``` roles/ common/ tasks/ main.yml vars/ main.yml templates/ my.cnf.j2 ``` 上面的Role定义了一个名为common的角色,它包含了一个tasks目录、一个vars目录和一个templates目录。其中,tasks目录包含了一个名为main.yml的任务文件,vars目录包含了一个名为main.yml的变量文件,templates目录包含了一个名为my.cnf.j2的模板文件。 以上就是Ansible的安装步骤和核心组件详解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值