tmp.md

打桩机制讨论

before:

  1. 打桩模块只关系数据的类型和数据元素的大小;
    如几乘几的矩阵,矩阵元素分别是什么?
  2. 打桩不需要关心提供多少数据。
    对数据量的要求,仅后端模块可见。

now:
模块以包的形式被驱动,包内部有多少数据,需要前级模块和后级模块都可见,相较于旧架构,新架构要求打桩模块完全知晓包内的数据量

由此对打桩带来的影响,可分两种情况讨论:

  1. 后级模块需要的包内的数据仅两个值可变(即空包或者特定大小的包)
  2. 后级模块需要的包内的数据多个值可变

分析结论是:如果是Case1,可以使用一些低代价的改动来规避问题。如果是Case2,需要用较为复杂的方式解决。

CASE 1:
空包或者特定大小的包后级模块可以感知。
可以使用如下写法规避问题:

代码风格A

if(Scheduled)
{
    if(condition)
    {
            // 如果实际场景来的是空包,但是打桩发的是非空包,该分支不会被执行
        portA_data_rate = x;
        pointer_to_portA = getIn("portA_name", portA_data_rate);
    }
    if(condition)
    {
        portA_data_rate = x;
        pointer_to_portB = getIn("portB_name", portB_data_rate);
    }

}

解释:
如果打桩是给特定大小的包,且在当前case,收到的应该是空包。那么该写法可以不使用getIn宏来获取包内数据,此时打桩模块发送的包只起到驱动的作用。

PS:
该写法只能适配单用户场景,如果是多用户场景。一部分用户的包是空包,一部分用户的包不是空包。
打桩模块发送的都是和用户数有关的非空包,不能自动区分空包和非空包。
该场景可以使用包透传机制实现,包透传机制将数据包以包为粒度获取下来。
使用宏getInIntPacketPointer("port_name", port_packet_num)即可使用包透传机制。
接着使用包的成员函数get_data()或者get_size()按需要获取或者写数据。
(示例:目前为适配打桩和测量的输入,信道估计暂使用该机制实现)

在CASE1下,打桩的包只有两种形式,空或者不空,打桩模块可以统一按非空实现。接收模块按需去取非空包。

不管是使用风格A的代码写法,还是使用包透传机制,这么做带来的一个问题是:弱化了包数据量大小的校验功能
这个功能是新架构一个很好的功能,避免了前后模块数据量的不一致,避免了收发端对数据的“要求”不一致。

不同于如下风格的代码:
风格B

if(Scheduled)
{
    if(conditionA)
    {
        portA_data_rate = x;
    }
    if(condition)
    {
        portB_data_rate = y;
    }
    pointer_to_portA = getIn("portA_name", portA_data_rate);
    pointer_to_portB = getIn("portB_name", portB_data_rate);
}

这样的写法对所有包进行强制数据量大小的校验,但是带来的问题是,打桩模块必须动态识别是发空包还是发非空包

为了简便考虑,CASE 1 可以暂时使用风格A的代码规避打包的问题。

CASE 2:后级模块需要的包内的数据多个值可变

该问题我认为很难存在低代价的解决方法,打桩模块不再能做成通用的了。
打桩需要完全适配后级模块的需求。

因为CASE2的存在,新架构下如何完全替代打桩模块的功能就是一个复杂的问题了。

大家讨论了集中可能的替代方法,总结如下:

  1. 打桩做成打包,这也是链路调试初期的通行做法。这样的问题是需要打包的模块必须连带一个特定的打包模块,模块数增多。
  2. 打桩功能合并到上级模块

第一种做法的代价是明显的,大家都写过打包,都有感知。

第二种做法的代价:
以测量和信道估计为例,在打桩模式下,测量模块就根据设定的端口速率输出打桩值
(进一步,可要求每个模块都支持打桩模式作为缺省模式,类似于C++的每个类都会有个缺省构造函数)
这样在具体算法实现前,有如下好处:

  1. 依靠打桩模式就可以让全链路就可以跑起来(当然结果未必正确)
  2. 对于上级模块来说,端口速率本来就是要计算的,并没有增加太多代码量,只是根据参数选择是否旁路实际算法
  3. 免得打桩的时候还要重新连线配参数(打桩值可以固定配在输出模块的参数里)

具体评估下第二种做法的代价:
如果使用第二种做法,不建议使用风格A型的代码,建议使用风格B的代码。

风格B的代码分为如下三步

  1. 所有模块的端口速率都算好
  2. 调用getIn, getOut获取包的内存
  3. 对内存进行读写

此时是输出打桩值还是输出算法值,区别仅在与步骤3.
那么需要增加的代价就是:

  1. 部分风格A的代码需要重构下
  2. 步骤3需要有两个分支:正常的算法分支,设置打桩值分支
    到这一步,我想方法2的3个好处就看的出来了。

那么问题在于,这么做,打桩的粒度需要作出什么样的,是模块级的,还是端口级的,还是不同模块可以设置不同级别。

讨论:

  1. 打桩还有其他觉得更好的方法么?
  2. 如果式方法2,大家觉得实现代价如何?

你可能感兴趣的:(tmp.md)