如何百倍加速 Lo-Dash?引入惰性计算

原文:How to Speed Up Lo-Dash ×100? Introducing Lazy Evaluation.
作者: Filip Zawada

译文:如何百倍加速 Lo-Dash?引入惰性计算
译者:justjavac



我一直以为像 Lo-Dash 这样的库已经不能再快了,毕竟它们已经足够快了。
Lo-Dash 几乎完全混合了各种 JavaScript 奇技淫巧(YouTube)来压榨出最好的性能。

惰性计算

但似乎我错了 - 其实 Lo-Dash 可以运行的更快。
你需要做的是,停止思考那些细微的优化,并开始找出更加适用的算法。
例如,在一个典型的循环中,我们往往倾向于去优化单次迭代的时间:

var len = getLength();
for(var i = 0; i < len; i++) {
    operation(); // <- 10毫秒 - 如何优化到9毫秒?!
}

代码说明:取得数组的长度,然后重复执行 N 遍 operation() 函数。译注 by @justjavac

但是,这(优化 operation() 执行时间)往往很难,而且对性能提升也非常有限。
相反,在某些情况下,我们可以优化 getLength() 函数。
它返回的数字越小,则每个 10 毫秒循环的执行次数就越少。

这就是 Lo-Dash 使用惰性计算的思想。
这是减少周期数,而不是减少每个周期的执行时间。
让我们看看下面的例子:

function priceLt(x) {
   return function(item) { return item.price < x; };
}
var gems = [
   { name: 'Sunstone', price: 4  },
   { name: 'Amethyst', price: 15 },
   { name: 'Prehnite', price: 20 },
   { name: 'Sugilite', price: 7  },
   { name: 'Diopside', price: 3  },
   { name: 'Feldspar', price: 13 },
   { name: 'Dioptase', price: 2  },
   { name: 'Sapphire', price: 20 }
];

var chosen = _(gems).filter(priceLt(10)).take(3).value();

代码说明:gems 保存了 8 个对象,名字和价格。priceLt(x) 函数返回价格低于 x 的所有元素。译注 by @justjavac

我们把价格低于 10 美元的前 3 个 gems 找出来。
常规 Lo-Dash 方法(严格计算)是过滤所有 8 个 gems,然后返回过滤结果的前 3 个。

不难看出来,这种算法是不明智的。
它处理了所有的 8 个元素,而实际上我们只需要读取其中的 5 个元素就能得到我们想要的结果。
与此相反,使用惰性计算算法,只需要处理能得到结果的最少数量就可以了。
如图所示:

我们轻而易举就获得了 37.5% 的性能提升。
但是这还不是全部,其实很容易找到能获得 1000 倍以上性能提升的例子。
让我们一起来看看:

// 99,999 张照片
var phoneNumbers = [5554445555, 1424445656, 5554443333, … ×99,999];

// 返回包含 "55" 的照片
function contains55(str) {
    return str.contains("55");
};

// 取 100 张包含 "55" 的照片
var r = _(phoneNumbers).map(String).filter(contains55).take(100);

在这个例子中,mapfilter 用来处理 99,999 个元素。
不过我们只需要它的一个子集就可以得到想要的结果了,例如 10,000 个,
性能提升也是非常大的(基准测试):

Pipelining

惰性计算带来了另一个好处,我称之为 "Pipelining"。
它可以避免链式方法执行期间创建中间数组。
取而代之,我们在单个元素上执行所有操作。
所以,下面的代码:

var result = _(source).map(func1).map(func2).map(func3).value();

将大致翻译为如下的常规 Lo-Dash(严格计算)

var result = [], temp1 = [], temp2 = [], temp3 = [];

for(var i = 0; i < source.length; i++) {
   temp1[i] = func1(source[i]);
}

for(i = 0; i < source.length; i++) {
   temp2[i] = func2(temp1[i]);
}

for(i = 0; i < source.length; i++) {
   temp3[i] = func3(temp2[i]);
}
result = temp3;

如果我们使用惰性计算,它会像下面这样执行:

var result = [];
for(var i = 0; i < source.length; i++) {
   result[i] = func3(func2(func1(source[i])));
}

不使用临时数组可以给我们带来非常显著的性能提升,特别是当源数组非常大时,内存访问是昂贵的资源。

延迟执行

和惰性计算一起使用的是延迟执行。
当你创建一个链,我们并不立即计算它的值,直到 .value() 被显式或者隐式地调用。
这种方法有助于先准备一个查询,随后我们使用最新的数据来执行它。

var wallet = _(assets).filter(ownedBy('me'))
                      .pluck('value')
                      .reduce(sum);

$json.get("/new/assets").success(function(data) {
    assets.push.apply(assets, data); // 更新我的资金
    wallet.value(); // 返回我钱包的最新的总额
});

在某些情况下,这样做也可以加速执行时间。我们可以在前期创建复杂的查询,然后当时机成熟时再执行它。

Wrap up

懒惰计算并不是行业里的新理念。它已经包含在了许多库里面,例如 LINQLazy.js 等等。我相信 Lo-Dash 和这些库最主要的区别是,你可以在一个更新的、更强大的引擎里面使用原有的 Underscore API。不需要学习新的库,不需要修改代码,只是简单升级。

但是,即使你不打算使用 Lo-Dash,我希望这篇文章启发了你。
现在,当你发现你的应用程序存在性能瓶颈,不要仅仅是去 jsperf.com 以 try/fail 风格优化它。
而是去喝杯咖啡,并开始考虑算法。
最重要的是创意,但良好的数学背景会让你如鱼得水(book)。祝你好运!

时间: 2024-10-14 18:15:21

如何百倍加速 Lo-Dash?引入惰性计算的相关文章

九樱vinux:电商模式付费转化率提升百倍

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 为扭转当下电商转化率普遍低迷的大情势,国内领先的电商平台九樱历时6年研发VINUX系统,被业界称为具有"颠覆性"创新模式的新核武器,成为首次成交转化率和高重复消费率的第三代电子商务系统,其付费转化率可提升百倍. 在SNS.微博流行的自媒体时代,不少消费者会首先通过网络获得翔实的信息,他们不再完全相信企业主动推介的商品广告信

自学习芯片、实时3D表情捕捉渲染,百倍DNN模型无损压缩 | 英特尔中国研究院媒体开放日

在人工智能的大背景下,这几年,说起芯片霸主英特尔,似乎总有一股时过境迁的味道.但是,"关于芯片霸主这个问题,判断是不是具有领先性,既不能看近期的市场营收,也不能只看媒体曝光的热度,应该要从一个长时期来看这家企业在整个芯片市场上的技术领先程度.对于下游厂商的支持程度,以及驱动整个生态系统的能力." 英特尔中国研究院院长宋继强说:"打个比方,如果一家芯片公司退出市场,这个世界会怎么样?大家可以想一下,有什么样的芯片企业是这个世界不能缺少的." 明年就是英特尔成立第50周

腾讯云推”百分服务” 承诺故障百倍赔偿

日前,腾讯公司副总裁.腾讯云负责人邱跃鹏在2014腾讯全球合作伙伴大会"大云端 大生态"峰会演讲中提及腾讯云的"百分服务"体系,大打服务牌.作为中国最大的云服务提供商之一,腾讯云"百分服务"承诺提供包括故障百倍赔偿.5天无理由退货.免费备案.大客户一对一.7*24小时等在内的补偿政策及专业服务.业内人士认为,腾讯云这一引入无理由退货及赔偿机制的举动,表达了腾讯云通过服务来赢得用户的决心,此举将有助于提升国内云计算服务的整体水平. 百倍赔偿与专业人

千百倍的性能提升-Andrew大师谈数据库性能优化

在今年3月份RWP中国之旅技术分享活动期间Andrew大师和AWR之父Graham接受了记者采访,首次对外讲述自己的职业生涯和心路历程,分享了他们在中国的感受和期待,并就当前IT系统现状做了深入分析,表达了RWP团队的使命和宗旨,同时也对广大技术爱好和追求者给出了中肯的建议和指导. 本文为采访原文,若需要阅读中文版,请查看: 甲骨文副总裁谈性能优化:百倍和千倍的性能提升才值得兴奋 Xue:First of all, it is an honor to have to you here one m

300亿美元小米豹变:雷军秘密造车 晨兴启明暴赚百倍

在互联网界,小米科技有限责任公司(下称小米)绝对是一个传奇.它就像一个刹不住车的雪球,越滚越大,超出了雷军和所有投资人的预期. 有谁会想到,4年前,一个名不见经传的"小米"手机"被迫"诞生. 小米手机本来只是想为雷军的软件MIUI铺路,没想到它不仅打垮了萌芽中的山寨智能手机,甚至还有赶超已发展十多年的国产老牌手机之势,销售额超300亿元. 2014年,小米越发红得发紫. 先是传出腾讯入股的绯闻,后又正式宣布涉足电动车领域. 3月26日,被小米副总裁黎万强认为是一个绝

顶级VC/PE拿走百倍回报:一级市场榨干二级市场

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 光鲜背后的险恶:一级市场榨干二级市场 顶级VC/PE拿走百倍回报,退出后股价大跌 2011年大幕落下,PE/VC一年的座次已经排定.南都记者从投中集团所获得的2011年VC/P E A股IPO退出回报数据显示,依照账面回报率和账面退出回报两项统计口径排名显示,新天域资本投资的华锐风电以184.5倍账面回报率和IPO账面回报108亿人民币拿下两

启迪创投罗茁“孵化人”之旅:十年数百倍回报

罗茁,清华科技园启迪创业投资管理有限公司董事长.董事总经理,启迪控股股份有限公司副总裁,全面负责启迪创投的战略发展和投资业务. 在罗茁看来,投资和远行.登山.摄影一样,都需要持之以恒的坚持和不辍的跋涉,都需要精心的准备和"该出手时就出手"的果断.靠着这份永不停歇的执著和对时机的精准把握,罗茁带领着他的团队,在本土PEVC,即私募股权基金和风险资金投资市场中,牢牢占据着一块属于自己的地盘. 启迪创投:一个"番号"的前世今生 2001年3月成立的清华科技园孵化器有限公司

延续摩尔定律: 新型超平面锡氧半导体材料有望让芯片提速百倍

近年来,半导体行业总是笼罩在摩尔定律难以为继的阴霾之下,但是新材料的出现,或可让它迎来又一个拐点.美国犹他州大学的工程师们,已经发现了一种由一氧化锡制成.只有单原子厚度的新型平面材料.这种材料可让电荷以更快的速度通过,远胜硅与其它3D材料.相比之下,在传统电子设备上,电荷会以各个方向穿过晶体管.以及玻璃衬底上其它由硅层组成的部件. 采用锡氧材料打造的更快的半导体器件 直到近年,工程师们才更多地将目光放到了诸如石墨烯(graphene).二硫化钼(molybdenum disulfide).硼墨烯

库巴CEO:电商外部经营成本数年翻百倍

TechWeb编辑推荐:与2010年电子商务(以下简称"电商")的高调大热不同的是,2011年电商开始逐渐冷却,尤其是进入到下半年,电商从投资的宠儿变 成了前途未卜频遭质疑的弃儿,其身份在短短几个月内发生了颠覆性的变化.昨日,国美电器旗下的库巴购物网CEO王治全对本报记者表示,如今电商经营的外部媒体成本过高,"一个导航的位置每月就要几百万元,比前几年翻了100倍都不止",面对不划算的成本产出,电商必须从其专长的"流量管控"向"品牌塑造&