今天在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)
{
}
综上,我们可以看出来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)
return s;
}
上面的这个程序就是简简单单地,一个字节一个字节地赋值了。
和memset.c相比,这个程序有如下缺点:
1:总线效率低。因为写内存次数多。
2:循环次数太多。每一次循环都要判断要不要跳转,所以循环次数太多造成不必要的判断太多。
有一个优点:简单易懂。
大学时候,选了一门C语言课,那老师很郁闷,因为他学了多年的计算机,不知道总线是什么,还在那儿骂计算机系的人(他不是计算机系的,好多院系都学计算机),说计算机系的把总线搞的那么玄。他还说为什么要有strlen,memset等这样的库函数,说这样的函数太容易写了,给他一分钟他就可以写出来。现在想想,读的书少不是好事。就像凤姐一样,读那么少的书,以为知音,故事会就是人文社科类的书了。呵呵。。