javascript减少循环迭代次数(”Dufff's Device算法“与“分时处理”)

原创 2011年10月19日 23:41:30

<<高性能JavaScript>>中有一章提到对循环进行优化,策略之一就是减少循环迭代次数:

大家可能都听过C语言实现的“达夫设备”算法(Duff's Device),Jeff Greenberg被认为是将”达夫设备“代码从原始的C实现移植到JavaScript中的第一人,一个典型实现如下:

//为了方便调用,把它封装成一个函数

function duff(items) {
    var len = items.length, //缓存局部变量
        iterations = Math.floor(len / 8),  //商数,存放duff迭代次数
        startAt = len % 8,    //余数,存放duff一次迭代调用process的次数
        i = 0;
        
    do {
        switch(startAt) {
            case 0:
                process(items[i++]);
            case 7:
                process(items[i++]);
            case 6:
                process(items[i++]);
            case 5:
                process(items[i++]);
            case 4:
                process(items[i++]);
            case 3:
                process(items[i++]);
            case 2:
                process(items[i++]);
            case 1:
                process(items[i++]);
        }
        
        startAt = 0;
    } while(iterations--);    //书上是--iterations,貌似不对吧,应该是iterations--
};

Duff’s Device背后的基本理念是:每次循环中最多可调用8次process()。循环的迭代次数iterations为总数除以8,startAt用来存放余数,表示一次循环中应调用多少次process()。

假设我们定义process函数为:

function process(item) {

      alert(item);

};

调用一下duff函数:

duff([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);  //依次弹出1~12

//在这个调用过程中,我们可以知道iterations为1,startAt为4,也就是说,循环了两次,第一次循环调用process函数4次,第二次循环调用了8次。

可见,可以满足我们的遍历需求,而据书中介绍,如果迭代次数超过1000次,duff遍历算法的执行效率将明显提升。


据书中介绍,该算法有一个稍快的版本如下:(取消了switch语句,并将余数处理和主循环分开)

function duff2(items) {
    var len = items.length,
        i = len % 8;
    
    while(i) {
        process(items[i--]);
    };
    
    i = Math.floor(len / 8);
    while(i){
      process(items[i--]);
      process(items[i--]);
      process(items[i--]);
      process(items[i--]);
      process(items[i--]);
      process(items[i--]);
      process(items[i--]);
      process(items[i--]);
    }
};

<<高性能JavaScript>>这本书中是这样写这个算法的,不过仔细一看就知道,这个算法明显有问题,它无法遍历一个完整的数组,正确的算法应该是:

function duff2(items) {
    var len = items.length,

         t = 0,
        i = len % 8;
    
    while(i--) {
        process(items[t++]);
    };
    
    i = Math.floor(len / 8);
    while(i--){
      process(items[t++]);
      process(items[t++]);
      process(items[t++])
      process(items[t++]);
      process(items[t++]);
      process(items[t++]);
      process(items[t++]);
      process(items[t++]);
    }
};

这里有个老外写的Duff's device各种优化方法

这个算法对于处理数据量比较大的数组,还是很有执行效率的,比如对于处理省、市、区等级联下拉框的时候,如果你用数组来存放这些数据的话,就可以使用这个算法来遍历数组,可以感觉明显快很多。


还有一种优化数组遍历的方法,“分时处理”,这里有个不错的解析:

这个方法用着有点不放心(毕竟内部存在着定时器,搞不好数组还没遍历并更新完成,后面的代码都快执行完了,如果这个时候,后面的代码需要使用这个被遍历的数组,那更悲剧了,拿到的不一定是新数组),呵呵,视具体情况而定,比如说:

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];

//我现在想用分时处理的方式来遍历这个数组
chunk(a, function(v, i) { 
    a[i] = v + 1; // 假如我想在这里这个数组的每一项都+1
}, window);

//那么假如接下来,我想立即使用这个已经更新过的数组
console.log(a.toString());  //结果得到啥?

setTimeout(function() {
    console.log(a.toString()); //这里又是啥?
}, 100);


//未完待续,临时有事,晚上回去再继续~~~


先写到这里,不保证文章的正确性,仅供参考!

Python:用迭代器和生成器降低程序内存占用率

情况描述:用一个30行代码的python文件,处理300M的数据,用到的数据结构有:pandas.DataFrame(), list, dict,二重循环,处理完一次写入磁盘。 问题:内存占用率97%...
  • ztf312
  • ztf312
  • 2017年01月12日 09:54
  • 1473

MATLAB中的三种循环

FOR 循环 在for和end语句之间的{commands}按数组中的每一列执行一次。在每一次迭代中,x被指定为数组的下一列,即在第n次循环中,x=array(:, n)。 如» for n=1:...
  • zhengzezi
  • zhengzezi
  • 2016年04月29日 17:20
  • 2638

Python大数据处理代码性能优化

如何加速你的python程序
  • ybdesire
  • ybdesire
  • 2016年07月25日 22:46
  • 2192

LR:LR中的迭代次数设置

在参数化时,对于一次压力测试中均只能用一次的资源应该怎么参数化呢?就是说这些资源用了一次就不能在用了的。   --参数化时,在select  next row选择unique,update va...
  • he_jian1
  • he_jian1
  • 2014年12月03日 13:09
  • 6918

lr压力测试的迭代次数

通过用lr做负载压力测试过程发现,如果设定不同的action迭代次数,每次得出的结果是不同的,曲线的表现形式也是不同的。这点就使我们会感觉困惑,为什么要设置action的迭代次数?以及对于不同的应用系...
  • fanfan_821
  • fanfan_821
  • 2011年09月16日 17:42
  • 1734

感知器算法(C语言)模式识别几何分类发(线性可分时)感知器算法(3维C语言实现)

#include #include #define C 1 void main() { //s[]用于记录各点坐标乘积; //arrey[]用于存放将输入点变换后的点 int i,j,k,N1,...
  • jg1681988
  • jg1681988
  • 2013年08月23日 23:11
  • 1186

linux进程调度算法:分时调度策略、FIFO调度策略、RR调度策略

linux内核的三种调度方法: SCHED_OTHER 分时调度策略, SCHED_FIFO实时调度策略,先到先服务 SCHED_RR实时调度策略,时间片轮转 注意: 实时...
  • qq_32811489
  • qq_32811489
  • 2017年04月25日 22:53
  • 279

嵌入式系统分时任务调度算法实现

嵌入式高级特性编程之管理你的任务   2014酷玩创意     直奔主题,今天我们讲的是定时任务处理。简单讲就是我有一系列的任务需要在将来的某个特定时间由系统去处理。补充一下这里的将来去处理...
  • KuWanChuangYi
  • KuWanChuangYi
  • 2014年06月02日 13:22
  • 812

支持向量机浅析(1):训练数据线性可分时的算法

例子   给定数据 xix^i 和标签 yiy^i,比如: xix^i yiy^i (2,3) -1 (3,2) -1 (5,7) +1 ...
  • quicmous
  • quicmous
  • 2016年11月30日 10:43
  • 402

感知器算法(C语言)模式识别几何分类法(线性可分时)感知器算法(2维C语言实现)

#include #include #define C 1 void main() { //s[]用于记录各点坐标乘积; //arrey[]用于存放将输入点变换后的点 int i,j,k,N1,...
  • jg1681988
  • jg1681988
  • 2013年08月23日 23:03
  • 641
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:javascript减少循环迭代次数(”Dufff's Device算法“与“分时处理”)
举报原因:
原因补充:

(最多只允许输入30个字)