哨兵节点
作者:互联网
1、概述
今天和同事一起调代码,定位到一处很耗时的地方,在某个线程中,同步周期需要保证在2ms(如果耗时不到2ms,那么让剩下的时间进行sleep).
但是在调用一个模块的内部函数时,时不时的就飘到了3~5ms,时间抖动毫无保证。后来仔细分析了一下被调用的函数,发现是在查找链表中某个目标节点时,由于目标节点的不确定行,导致耗时飘来飘去。
后来想到是否可以用“哨兵”的思路来解决问题,于是就试了一下,果然有效。特分享于此,使用2段代码来看一下代码执行效率的提升。
2、普通的算法
所谓哨兵,就是一个标志,一个与查找目标对象一样的操作对象。
假如有1000000个纸箱,每个箱子里面有一个纸条,里面写有1~1000000这些数字,数字不会重复。现在别人给一个随机的数字,我们需要从这1000000个箱子里找到与这个数字相同的纸条,找到之后退出操作。
分析:纸箱是无序的,所以我们需要从头遍历
(1)代码1
我们给一个500000的数字,要在这1000000个箱子中寻找纸条数字为500000
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/time.h> #define LOOP_NUM 1000000 int main(void) { long data[LOOP_NUM]; long rand_num = 500000; struct timeval tv1, tv2; for (long i = 0;i < LOOP_NUM;i++) { data[i] = i; } gettimeofday(&tv1,0); for (long i= 0;i<LOOP_NUM;i++) { if (data[i] == rand_num) { printf("find the box %ld\n",data[i]); break; } } gettimeofday(&tv2, 0); long us1 = tv1.tv_sec * 1000000 + tv1.tv_usec; long us2 = tv2.tv_sec * 1000000 + tv2.tv_usec; printf("time elapse %ld\n",us2-us1); return 0; }
我们使用for循环遍历所有的箱子查找,我们可以看到查找花了2840us.
(2)代码2(哨兵节点)
int main(void) { long data[LOOP_NUM+1]; long rand_num = 500000,i=0; struct timeval tv1, tv2; for (long i = 0;i < LOOP_NUM;i++) { data[i] = i; } data[LOOP_NUM] = 500000; /*增加一个哨兵节点*/ gettimeofday(&tv1,0); while(1) { if(data[i] == rand_num) { printf("find the box %ld\n",data[i]); if(i==LOOP_NUM) { printf("find the sentinal box\b"); } break; } i++; } gettimeofday(&tv2, 0); long us1 = tv1.tv_sec * 1000000 + tv1.tv_usec; long us2 = tv2.tv_sec * 1000000 + tv2.tv_usec; printf("time elapse %ldus.\n",us2-us1); return 0; }
执行结果:
使用哨兵后,很明显提高了代码执行效率,代码1中使用for循环中对于i的最大值每个循环都要进行比较判断,这就降低了代码的执行效率,代码2加入了哨兵节点,多一个纸箱,纸箱里面的纸条写成500000。如果一直查找到哨兵节点才退出循环,表示没有找到。代码2中我们使用while循环,没有了每次箱子最大数量的比较判断,这就增加了代码的执行效率。
标签:tv1,long,哨兵,NUM,1000000,data,节点,LOOP 来源: https://www.cnblogs.com/yuanqiangfei/p/16347258.html