使用缓存来提高开发性能 - 算法优化
最近浏览关于性能的博客比较多,
无论是拼图/懒加载等傻瓜式优化,还是逻辑上的选用设计模式等系统优化,
感觉都是挺好玩的,今天就来讲讲缓存在网站开发中的重要性。
计算斐波那契数列,也叫黄金分割数列(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 哟