• 哨兵节点


    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循环,没有了每次箱子最大数量的比较判断,这就增加了代码的执行效率。

     

     

  • 相关阅读:
    1347: Last Digit (周期函数)
    1363: Count 101 (经典数位dp)
    1360: Good Serial Inc.(不知道是什么类型的题)
    C#winForm调用WebService的远程接口
    Web Service 的创建简单编码、发布和部署
    极致精简的webservice集成例子
    SVN使用教程总结
    C# int.Parse()与int.TryParse()
    C# 函数1 (函数的定义)
    C#中的委托和事件
  • 原文地址:https://www.cnblogs.com/yuanqiangfei/p/16347258.html
Copyright © 2020-2023  润新知