前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DAOS高性能设计之网络上下文内存池(复用HG内存控制器)

DAOS高性能设计之网络上下文内存池(复用HG内存控制器)

原创
作者头像
晓兵
发布2023-11-01 23:25:48
2490
发布2023-11-01 23:25:48
举报
文章被收录于专栏:daosdaos

DAOS高性能设计之CART上下文复用(内存池)

优势

1. 免去每次申请内存的开销

2. 动态扩容, 内存池中元素不够时,动态增长

3. 预分配和最大内存个数, 控制内存使用

核心流程总结

1. 在创建网络上下文(crt_context_create)的时候, 初始化内存池(crt_hg_pool_init)

2. 初始化自旋锁(D_SPIN_INIT), 池链表(D_INIT_LIST_HEAD), 设置池元素最大个数(512)和预分配个数(16)并启用内存池(crt_hg_pool_enable)

3. 按预分配个数, 准备上下文(HG_Create), 插入池队列尾部(d_list_add_tail)

4. 发送RPC时, 从池中获取上下文(crt_hg_pool_get), 从池队列头部弹出一个元素并返回(d_list_pop_entry)

5. 获取后判空, 如果池子为空, 则扩容, 即创建上下文(HG_Create)

6. RPC用完后, 通过减引用计数(RPC_DECREF(RPC))中去销毁cart请求(crt_req_destroy)

7. 重置请求上的内存(HG_Free_output), 终结清空RPC(crt_rpc_priv_fini(rpc_priv))

8. 如果是单个RPC(!crp_coll), 且不是服务端的接收RPC请求(!crp_srv), 且RPC是需要回复(!coi_no_reply), 则将该上下文放回内存池(crt_hg_pool_put, d_list_add_tail)

9. 返回内存池时, 判断是否池满, 池满则直接销毁上下文(D_FREE(hdl))

CART发送RPC的参考调用栈如下

代码语言:javascript
复制
crt_req_send(req, shard_update_req_cb, remote_arg)  complete_cb = shard_update_req_cb
    crt_context_req_track
        crt_set_timeout
        epi_req_waitq 如果拥塞就进等待队列
        crt_req_timeout_track
        epi_req_q 否则进飞行队列
    crt_req_send_internal
        crt_req_ep_lc_lookup
            crt_req_send_immediately
                crt_hg_req_create -> 创建请求
                    if (!rpc_priv->crp_opc_info->coi_no_reply) -> 双边(需要回复/响应)
                    rpcid = CRT_HG_RPCID
                    rpc_priv->crp_hdl_reuse = crt_hg_pool_get(hg_ctx) -> 复用HG内存控制器(从内存池获取), 自旋锁, 弹出并返回, 计数器减1
                        D_SPIN_LOCK(&hg_pool->chp_lock)
                        hdl = d_list_pop_entry(&hg_pool->chp_list
                        hg_pool->chp_num--
                        return hdl
                    else
                    rpcid = CRT_HG_ONEWAY_RPCID coi_no_reply:1 /* one-way */ 单程(无需响应,默认)
                    if (rpc_priv->crp_hdl_reuse == NULL) -> 如果内存池为空,则新建HG控制器
                    HG_Create
                      hg_core_create
                        hg_core_alloc_na 分配操作id
                    HG_Reset 重用 rpc_priv->crp_hdl_reuse
                crt_hg_req_send
                    HG_Forward(hdl, crt_hg_req_send_cb,...) 回调机制:forward_cb -> request_callback -> hg_cb(由HG_Trigger执行回调)
                        HG_Core_get_rpc_data
                        hg_set_struct
                            proc_cb in_proc_cb|out_proc_cb  crt_proc_common_hdr 被 HG_Register 注册
                        HG_Core_forward(...,hg_core_forward_cb,...)
                            forward(hg_core_handle) hg_core_forward_na|hg_core_forward_self
                                hg_core_forward_na
                                    hg_core_gen_request_tag
                                    NA_Msg_recv_expected hg_core_recv_output_cb NA_OFI_OP_RESET
                                    NA_Msg_send_unexpected hg_core_send_input_cb
                                        na_ofi_msg_send_unexpected
                                            na_ofi_msg_send
                                                fi_rx_addr index, bits, 偏移和位运算计算出地址
                                                fi_tsend -> rxm_ep_tsend
                                                    ssize_t rxm_get_conn 新建或复用连接
                                                    rxm_send_common
                                                na_ofi_op_retry -> na_ofi_cq_process_retries HG_QUEUE_POP_HEAD
        crt_req_hg_addr_lookup -> 见下面
查找目标地址:
crt_req_send -> crt_req_send_internal -> crt_req_ep_lc_lookup -> crp_hg_addr (na_addr) -> 地址作为 HG_Create 的参数(目的地址) -> crt_req_send_immediately -> crt_hg_req_create RPC_STATE_REQ_SENT 创建请求,设置状态为发送 -> crt_hg_req_send -> HG_Forward -> HG_Core_forward -> forward(hg_core_handle) -> hg_core_forward_na -> NA_Msg_send_unexpected -> na_ofi_msg_send_unexpected -> na_ofi_msg_send -> fi_tsend

目标地址: crp_tgt_uri
crt_req_send_internal -> crt_req_ep_lc_lookup -> crt_req_fill_tgt_uri -> crp_tgt_uri

crt_issue_uri_lookup


crt_req_hg_addr_lookup -> 根据url和标签查找NA地址, 我们有基本 URI 但没有标签的 NA 地址的情况
  HG_Addr_lookup2(crt_ctx->cc_hg_ctx.chc_hgcla, rpc_priv->crp_tgt_uri, &hg_addr) -> 根据目标url查询地址信息
  crt_grp_lc_addr_insert -> 缓存, 根据tag查找hg_addr, 填写crt_ctx的查找缓存中某个标签的hg地址。 在调用此例程之前,标签所在的主机等级必须存在于缓存中
    rank = crt_grp_priv_get_primary_rank(passed_grp_priv, rank) -> 获取主rank
    ctx_idx = crt_ctx->cc_idx
    rlink = d_hash_rec_find(&grp_priv->gp_lookup_cache[ctx_idx],(void *)&rank, sizeof(rank)) -> 根据上下文索引在缓存中查找rank
    li = crt_li_link2ptr(rlink) -> 根据链表找到列表条目
    li->li_tag_addr[tag] = *hg_addr -> 将tag作为key, hg_addr作为value存入标签_地址映射中

晓兵(ssbandjl)

博客: https://logread.cn | https://blog.csdn.net/ssbandjl | https://cloud.tencent.com/developer/user/5060293/articles

DAOS汇总: https://cloud.tencent.com/developer/article/2344030

公众号: 云原生云

晓兵技术杂谈(系列)

https://cloud.tencent.com/developer/user/5060293/video

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DAOS高性能设计之CART上下文复用(内存池)
    • 优势
      • 核心流程总结
        • CART发送RPC的参考调用栈如下
          • 晓兵(ssbandjl)
          • 晓兵技术杂谈(系列)
          相关产品与服务
          对象存储
          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档