鲲鹏社区首页
中文
注册
开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

减少memset的调

【说明】 内存操作函数memset/memset_s涉及到系统调用,其执行开销相对较大,尤其是在操作数据较大的场景下;因此对于大片内存,需合理设计其数据访问控制方式,应该减少memset的使用。

针对数据访问控制方式的建议如下:

  • 数据标志位指示方法:可以通过设置标志变量,清除标志变量来实现相同的效果。具体地,可以在一个结构体的成员变量前增加一个标志变量,该变量如果被置为无效,则表示数据被清空;注意:需要确保对数据访问前判断标志位,避免访问无效数据。
  • 字符串结束符标识方法:如果内存是用于存放字符串,可以利用填充字符串结尾‘\0’来优化。

【原理】

memset的性能分析(以Intel(R) Xeon(R) Gold 6161 CPU @ 2.20GHz为例):

memset

1k

1M

10M

1w次

180us

288ms

4300ms

【注意事项】 针对上述数据标志位指示方法字符串结束符标识方法,需要确保对数据进行访问之前,增加其有效性判断;另外,超过一定大小的结构体类型局部变量(需要注意的是,全局变量或静态变量的初始化不在此范围)使用“={0}”的方式进行初始化时,编译器也会隐式的调用memset,需要在编码阶段关注这种隐式调用。

【案例】

优化前
struct MsgInfo {
    uint8_t rawMsg[1000];
    uint8_t msgKeyword;
};

void MsgInit(MsgInfo &info)
{
    (void)memset_s(&info, sizeof(info), 0, sizeof(info));
}

说明:函数MsgInit参数info进行清零处理时,memset_s执行开销较大。

优化后
struct MsgInfo {
    bool msgIsValid;
    uint8_t rawMsg[1000];
    uint8_t msgKeyword;
};

void MsgInit(MsgInfo &info)
{
    info.msgIsValid = false;
}

说明:通过msgIsValid有效标识对数据结构的有效性进行判断,函数MsgInit仅需要对该标志变量进行清零。