memset效率

来源:互联网 发布:《疯狂java讲义》 编辑:程序博客网 时间:2024/06/06 03:12

今天在CSDN上有人聊memset的效率。凑巧,我这几天也看了看glibc的几个函数的实现。
下面就扯一扯DIR/string/memset.c
其中DIR是解压glibc后的路径。我下载的是glibc-2.11。

//代码经过astyle格式化
void *
memset (dstpp, c, len)
void *dstpp;
int c;
size_t len; //前几行等同于: void * memset(void *dstpp, int c, size_t len)
{
    long int dstp = (long int) dstpp;

    if (len >= 8)
    {
        size_t xlen;
        op_t cccc;
       
       
        cccc = (unsigned char) c;
        cccc |= cccc << 8;
        cccc |= cccc << 16; // 至此已经扩成了4字节。
        if (OPSIZ > 4)      // 如果是64位的机器,要扩成8字节
           
            cccc |= (cccc << 16) << 16;

       
        while (dstp % OPSIZ != 0) //首先将dstp对齐到OPSIZE, 一边对齐一边按字节赋值。此处为1号while
        {
            ((byte *) dstp)[0] = c;
            dstp += 1;
            len -= 1;
        }

       
       
        xlen = len / (OPSIZ * 8);
        while (xlen > 0)                                   // 2号 while
        {
            ((op_t *) dstp)[0] = cccc;
            ((op_t *) dstp)[1] = cccc;
            ((op_t *) dstp)[2] = cccc;
            ((op_t *) dstp)[3] = cccc;
            ((op_t *) dstp)[4] = cccc;
            ((op_t *) dstp)[5] = cccc;
            ((op_t *) dstp)[6] = cccc;
            ((op_t *) dstp)[7] = cccc;
            dstp += 8 * OPSIZ;
            xlen -= 1;
        }
        len %= OPSIZ * 8;//还有len字节没有写

       
       
        xlen = len / OPSIZ;
        while (xlen > 0)         // 3号while
        {
            ((op_t *) dstp)[0] = cccc;
            dstp += OPSIZ;
            xlen -= 1;
        }
        len %= OPSIZ;
    }

     
   
    while (len > 0)       //4号while
    {
        ((byte *) dstp)[0] = c;
        dstp += 1;
        len -= 1;
    }
    return dstpp;
}
综上,我们可以看出来memset在给一块内存赋值时采用的策略。
1:先把将要赋值的块的起始地址对齐。见1号while。
2:有大于等于8个OPSIZ长度未写,一次循环写8个OPSIZ长。 见2号while。
3:还有小于8个OPSIZ长度未写,一次循环写1个OPSIZ长。 见3号while。
4:还有小于OPSIZ长度未写,一次循环写1个字节。 见4号while。

下面看一看DIR/string/test-memset.c中的simple_memset.c

char *
simple_memset (char *s, int c, size_t n)
{
char *r = s, *end = s + n;
while (r < end)
    *r++ = c;
return s;
}
上面的这个程序就是简简单单地,一个字节一个字节地赋值了。
和memset.c相比,这个程序有如下缺点:
1:总线效率低。因为写内存次数多。
2:循环次数太多。每一次循环都要判断要不要跳转,所以循环次数太多造成不必要的判断太多。
有一个优点:简单易懂。

大学时候,选了一门C语言课,那老师很郁闷,因为他学了多年的计算机,不知道总线是什么,还在那儿骂计算机系的人(他不是计算机系的,好多院系都学计算机),说计算机系的把总线搞的那么玄。他还说为什么要有strlen,memset等这样的库函数,说这样的函数太容易写了,给他一分钟他就可以写出来。现在想想,读的书少不是好事。就像凤姐一样,读那么少的书,以为知音,故事会就是人文社科类的书了。呵呵。。

0 0
原创粉丝点击