使用缓存来提高开发性能 - 算法优化

最近浏览关于性能的博客比较多,

无论是拼图/懒加载等傻瓜式优化,还是逻辑上的选用设计模式等系统优化,

感觉都是挺好玩的,今天就来讲讲缓存在网站开发中的重要性。

 

计算斐波那契数列,也叫黄金分割数列(1,1,2,3,5,8,13...),同时也就是兔子繁衍问题,每一项等于前两项之和,

当然,数列项的其他操作就不在今天讨论的范围内了,比如 1/1=1, 1/2=0.5, 2÷3=0.666, ... 144÷233=0.618025 无限趋近于 0.618(黄金分割比)等,

计算第 n 个斐波那契数列项就需要用到下面这样的程序,

var count = 0;
function fib(n) {
  count++;
  if(n === 0 || n === 1) return 1;
  return fib(n-2) + fib(n - 1);
}
console.log(fib(40), count); // 运行了 331160281 次

显然这样来做理论上是对的,但计算量细思极恐,

如果我们可以把计算过了的项存在缓存里,不用计算下一项时又计算一次它,是不是能优化很多呢...

var count = 0;
var fib = (function() {
    var cache = [];
    return function(n) {
        count++;
        if(cache[n] !== undefined) {
            return cache[n];
        }
        if(n === 0 || n === 1) {
            cache[n] = 1;
            return cache[n];
        }
        var temp = arguments.callee(n - 1) + arguments.callee(n - 2);
        cache[n] = temp;
        return cache[n];
    };
})();
console.log(fib(40), count); // 运行了 79 次

 

发现一般使用递归都会使运行时间增长很多,于是乎,写了下面这段代码,

将缓存模式进行了封装,于是乎,无论是简单递归还是斐波那契数列都可以很轻易的提升性能了

// 测试性能
function testFunctionTime(fn, label) {
    console.time(label);
    if (fn) fn();
    console.timeEnd(label);
}
// 封装缓存机制
function useCache(fn) {
    var cache = {};
    return function(){
        var key = arguments.length + Array.prototype.join.call(arguments, ",");
        if (key in cache) return cache[key];
        else return cache[key] = fn.apply(this, arguments);
    }
}
// 斐波那契数列
function fn1() {
    var count = 0;
    var fib = function(n) {
        count++;
        if(n === 0 || n === 1) return 1;
        return fib(n - 1) + fib(n - 2);
    };
    console.log(fib(40), count);
}
function fn2() {
    var count = 0;
    var fib = useCache(function(n) {
        count++;
        if(n === 0 || n === 1) return 1;
        return fib(n - 1) + fib(n - 2);
    });
    console.log(fib(40), count);
}

testFunctionTime(fn1, '无缓存');
testFunctionTime(fn2, '有缓存');

嗯,效果非常 nice 哟

posted on 2016-10-21 15:54  永恒的浪荡时光  阅读(195)  评论(0编辑  收藏  举报

导航