淘宝店:[吴健英的店]
for(;;)
{
void * buffer = malloc(SIZE);
memset(缓冲区,大小);
进程(缓冲区)
自由缓冲区;
}
这是一个实习生的伪代码(我带了10+个实习生,见多识广)。本来这个SIZE很小,估计是用来存储URL的,定义为512字节。后来因为某种原因扩展到1M,从512字节扩展到1M,速度慢了很多。为什么?这位同学没法解释,但我让他继续探索,找出真正的原因。
我让他从这些方面入手。
(1)首先对一些耗时的代码进行分析,发现memset从512到1M花费的时间更多,且增加不是线性的。我让他先看看glibc的memset源代码,如下:
#如果定义了_LIBC ||定义了STDC_HEADERS ||定义了USG
#包括
#定义洪水记忆集
#否则
静态空洪(__ptr_t,int,_ _ malloc _ size _ t);
静态空隙
洪水(ptr、val、大小)
_ _ ptr _ t ptr
int val
_ _ malloc _ size _ t size
{
char * cp = ptr
while(大小-)
* cp++ = val;
}
#endif
可见memset是每个字节都赋值的,不是机器喜欢的方式。机器希望在4字节对齐的位置运行(32位机器,64位机器喜欢8字节对齐),一次读取32位(4字节)。因此,memset可以实现一次写入4个字节的代码。
(2) malloc需要进一步探索。事实上,linux内存分配有两种,brk和mmap。前者分配128 K以内的内存,后者分配128k以上的内存,改成1M后,
void * buffer = malloc(SIZE);
这一段很快,因为只分配虚拟内存,不加载内存。可以通过check /proc/pid/statm观察操作前后内存分配和memset的变化。
Memset需要实际内存分配、页面故障中断、TLB加载等等。
brk分配的内存是glibc管理的内存,分配快,释放方便(很多情况下不释放)。所以brk分配用的是512字节(效率高),但是改成1M后,用的是mmap分配(memset效率低),所以效率低很多。
(3)如果将此代码更改为,等效性能将大大提高。
void * buffer = malloc(SIZE);
for(;;)
{
memset(缓冲区,大小);
进程(缓冲区)
}
自由缓冲区;
(4)最后,需要质疑的是为什么要开一个1M大小的空房间,是否通过了验证,是否有必要这样做,实际情况如何,是否需要memset,是否可以通过其他方法避免。
可见,很多问题,编码习惯不好,对机器理解不足,在一般的工作中是很难发现的,必须体现在大规模数据处理的实际场合(处理的数据量足够大)。所以大规模数据处理技术是软硬件结合的技术,不仅仅是技术问题,还有业务问题。应该消除浪费代码和计算,不合理的计算应该变得合理。
本文来源于网络。如果原作者不支持我们转发,请联系我们删除。谢谢!
技术来自积累,成功来自坚持
1.《memset 关于程序效率的问题,你有思考过吗?》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《memset 关于程序效率的问题,你有思考过吗?》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/junshi/889445.html