hello

# 打桩机制讨论

**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,大家觉得实现代价如何?

你可能感兴趣的:(hello)