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

SAP ALV开发避坑:GETWA_NOT_ASSIGNED错误的根本原因与修复(基于EHP7) 本文深入解析SAP ALV开发中常见的GETWA_NOT_ASSIGNED错误,揭示其根本原因在于ABAP内存管理与对象生命周期问题。通过对比多种解决方案,推荐使用基于类的数据持久化方法,并提供高级调试技巧与防御性编程建议,帮助开发者彻底解决这一典型问题并提升报表稳定性。 阅读详情

原文: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 个。

Lodash naïve approach

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

Lo-Dash regular approach

我们轻而易举就获得了 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);

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

benchmark

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

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

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

lazyseq:惰性计算的Python序列类型 lazyseq:Python的惰性计算序列类型 lazyseq是一个简单的库,实现了单个类LazySeq ,该类提供了惰性计算的序列,可以像不可变列表一样使用。 您可以将其视为Clojure 的Python版本。 LazySeq的主要用途是包装生成器或,使它们持久化,但仍然很懒。 LazySeq工具Python的序列接口,因而具有方法__getitem__ , __len__ , __contains__ , __iter__ , __reversed__ , index和count 。 从LazySeq中获取项目等同于从提供的可迭代列表中获取项目。 但是,仅评估LazySeq的必要元素(所有达到最大请求元素的元素),并且所有评估的元素都缓存在LazySeq上,因此可以再次对其进行迭代。 请注意,某些操作(例如len(seq)将有必要遍历(并因此缓存)整个可迭代对象。 要使用Laz 立即下载

相关推荐

PaddleOCR GPU部署:从环境配置到避坑实战指南

本文详细介绍了PaddleOCR GPU部署的全过程,从环境配置到避坑实战指南。通过分析常见的部署失败原因,提供硬件兼容性自查、软件环境精配方案以及路径配置的解决方案,帮助用户高效完成GPU加速的OCR任务部署,避免90%的常见错误。

weixin_30839881的博客 419

Lo-Dash——实用的js工具库

         大家可以在   www.codefordream.com   练习。            在JS中,尤其对于菜鸟而言,代码都是重复兀杂的,Lo-Dash 等第三方javascript库可以改进我们的编码过程和编码质量。         下面是我们用的比较多的方法   _.map和_.find方法来精简代码:   下面是一个for循环复杂嵌套的例子:(其实完成的...

iteye_983的博客 481

Copula函数

Copula是处理统计中随机变量相关性问题的一种方法。本文是对Copula函数的各种定义,Copula函数的思想,Copula函数的性质,Copula函数的类型等理论资料总结

Explore 5万+

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

原文:How to Speed Up Lo-Dash ×100? Introducing Lazy Evaluation. 作者: Filip Zawada 译文:如何百倍加速 Lo-Dash?引入惰性计算 译者:justjavac 我一直以为像 Lo-Dash 这样的库已经不能再快了,毕竟它们已经足够快了。Lo-Dash 几乎完全...

weixin_34384915的博客 305

CANOe实战指南 - 从入门到精通的全流程解析

本文是CANOe实战指南,全面解析从入门到精通的全流程。内容涵盖CANOe软件的核心功能仿真、测试与分析,详细指导安装配置、工程创建、CAN信号收发、UDS诊断通信、CAPL自动化编程以及Panel面板设计。通过实战案例,帮助汽车电子工程师快速掌握这一行业标杆工具,构建自动化测试环境,提升开发与测试效率。

pear55的博客 575

关于VS2022创建winform窗体后择项或选择工具箱项加载visionPro控件卡住,窗口未响应解决方法

解决winform加载工具箱选择项卡死问题

xiaokiss_的博客 3213

惰性序列

在引入惰性序列之前我们需要知道什么是惰性计算。 惰性计算 惰性计算(Lazy Evaluation),又称懒惰计算、懒汉计算,是一个计算机编程中的一个概念,它的目的是要最小化计算机要做的工作。它有两个相关而又有区别的含意,可以表示为“延迟计算”和“短路求值”。 延迟计算: https://baike.baidu.com/item/惰性计算/3081216?fr=aladdin 延迟求值...

liu_liuqiu的博客 3463

PMF5.0计算

EPA PMF5.0 计算步骤

nuistsy的博客 4543

经典案例-惰性运算

惰性计算(Lazy evaluation),是指仅仅在真正需要执行的时候才计算表达式的值。充分利用其特性可以带来很多便利。函数,那么根据描述符和属性名冲突时的优先顺序,运行的结果就会发生区别了。函数就执行了两次,所以没有完成惰性运算,这就是将非数据描述符。将描述符与惰性运算结合起来。从上述代码可以看出,调用了两次。变成数据描述符的区别了。

qq_53183660的博客 510

华为设备OSPF配置全流程:从邻居关系到区域划分实战指南

本文详细介绍了华为设备上OSPF协议的完整配置流程,从基础概念到实战操作,包括邻居关系建立、多区域划分及高级特性配置。特别针对华为设备的特有语法和验证命令进行了重点讲解,帮助网络工程师快速掌握OSPF在华为环境中的部署与优化技巧,提升网络配置效率。

weixin_29299807的博客 251

玩转大语言模型——使用华为官方MindIE-Server镜像方式部署DeepSeek模型

本文将详细介绍在国产Linux系统欧拉中使用华为官方MindIE-Server镜像方式部署DeepSeek模型。一般情况下华为昇腾800I服务器可以推理DeepSeek-R1-70B,4张300I-Duo服务器可以推理DeepSeek-R1-32B。在配置中尽量贴合官方文档,包含用到的一些其他的技术细节,便于零基础入门使用。

艾醒的博客 1289

python 惰性序列_python 基础(三)

函数调用定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。如下实例调用了printme()函数:#!/usr/bin/python3# 定义函数defprintme(str):# 打印任何传入的字符串print(str)return# 调用函数printme("我要调用用户...

weixin_39528029的博客 398

28_Spring AI 干货笔记之 OpenAI 聊天功能

本文详细介绍了在Spring AI框架中集成OpenAI聊天模型的方法。内容涵盖API密钥配置、通过starter依赖启用自动配置、连接与模型参数的详细设置,并重点说明了运行时选项的动态覆盖机制。文章还深入讲解了多模态处理(图像与音频)、结构化输出、函数调用等高级功能,提供了示例控制器和手动配置指南,并讨论了与OpenAI兼容服务器的适配与推理模型思维链的获取。

在科技的浪潮中,我们寻找着创新的火种,在代码的海洋里,我们编织着智慧的网。腾飞开源,就是这样一个由技术精英汇聚而成的博客平台,我们致力于分享在Java、Python、IoT和人工智能等领域的最新研究成果和实战经验。 在腾飞开源的博客上,你会看到紧跟技术前 1657

python 惰性计算_【译】如何百倍加速 Lo-Dash?引入惰性计算

我一直以为像 Lo-Dash 这样的库已经不能再快了,毕竟它们已经足够快了。 Lo-Dash 几乎完全混合了各种JavaScript 奇技淫巧来压榨出最好的性能。惰性计算但似乎我错了 - 其实 Lo-Dash 可以运行的更快。 你需要做的是,停止思考那些细微的优化,并开始找出更加适用的算法。 例如,在一个典型的循环中,我们往往倾向于去优化单次迭代的时间:var len = getLength();...

weixin_39614094的博客 118

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

java函数式编程性能不好_JavaScript 函数式编程的性能问题

原标题:JavaScript 函数式编程的性能问题clean-code-java 是 github 上的一个项目,旨在教 java 程序员写出简洁易于维护的代码,其中有一条是 Favor functional programming over imperative programming。作者以两段代码说明:Bad:constprogrammerOutput=[{name:'Uncle Bobby...

weixin_35733495的博客 501

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

JavaScript 函数式编程的性能问题

clean-code-javascript 是 github 上的一个项目,旨在教 javascript 程序员写出简洁易于维护的代码,其中有一条是 Favor functional programming over imperative programming。作者以两段代码说明: Bad: const programmerOutput = [  {    na

justjavac的专栏 862

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Python 的惰性求值与惰性序列

惰性求值 在编程语言理论中,惰性求值(英语:Lazy Evaluation),又译为惰性计算、懒惰求值,也称为传需求调用(call-by-need),是一个计算机编程中的一个概念,它的目的是要最小化计算机要做的工作。它有两个相关而又有区别的含意,可以表示为“延迟求值”和“最小化求值”。 避免不必要的计算,带来性能的提升(最小化求值)。  对于Python中的条件表达式 if x and y,在...

weixin_42102929的博客 3151

js工具类Lodash、功能介绍、用法

Lodash 是一个非常流行的 JavaScript 实用工具库,它提供了一系列优化后可重复使用的函数,简化了 JS 开发中各种常见任务的编写。

weixin_39823006的博客 3682

Lodash实战:高效JavaScript工具库详解

Lodash是一个现代化JavaScript工具库,提供一致、模块化、高效的实用函数。主要特点包括:跨浏览器兼容、性能优化、丰富API(数组/对象/函数操作等)。安装方式灵活,支持多种构建版本(完整/核心/FP)。核心API包含数组处理(chunk/flatten)、集合操作(map/filter)、对象处理(get/set)、函数工具(debounce/curry)等。高级特性包括链式调用、惰性求值和函数式编程。虽然ES6+提供了部分原生替代,但Lodash在深度属性访问、性能优化和复杂操作上仍有优势。推

油墨香^-^的博客 1423

博客摘录「 惰性序列」

Python的惰性序列多数指 iterator,具有惰性计算特点的序列称为惰性序列。Python的iterator是一个惰性序列,意思是表达式和变量绑定后不会立即进行求值,而是当你用到其中某些元素的时候才去求某元素对的值。惰性是指,你不主动去遍历它,就不会计算其中元素的值。上述代码,执行到第四行代码r=map(f,[1,2,3,...])时,并未进行计算,执行到第五行代码list(r)才进行计算。

long_jing_1003的博客 274

【Java基础系列】什么是惰性求值?

惰性求值(Lazy Evaluation)是一种编程语言的特性,它在需要运算结果时才会进行计算,而不是在定义时就立即计算。这种方式可以避免不必要的计算,提高程序的效率。惰性求值通常用于函数式编程语言中,其中函数是一等公民,并且函数可以作为参数传递给其他函数。在惰性求值中,函数可以返回一个表达式,而不是一个具体的值。只有当这个表达式被需要时,才会对其进行计算并返回结果。这种方法可以减少计算的次数,尤其是在处理大规模数据集时非常有效。在这个例子中,filter 函数返回一个新的列表,包含满足条件的元素。

优快云站内信: https://i.youkuaiyun.com/#/msg/chat/qyj19920704 9475

lodash中debounce防抖实现和延时器防抖实现

handleChange (property, value) { this.debounce(property, value) }, debounce: _.debounce(function (property, value) { window.GDEGRAPHIC.setProperty(property, value) }, 1000),

weixin_41424721的博客 381

python 惰性序列_python学习

函数式编程1、几个高阶函数(1)mapmap(函数,Iterable)结果是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。将传入的函数依次作用到序列的每个元素例子:>>> def f(x):... return x * x...>>> r = map(f, [1, 2, 3, 4, ...

weixin_39642981的博客 641

lodash的用法详解

lodash是一个JavaScript语言的工具库,提供了很多实用工具函数,可以帮助我们更便捷地对数据进行操作。它的使用非常广泛,可以用于Web开发、后端开发等领域。

m0_64697285的博客 5279
上一篇: Flarum 安装
下一篇: Chrome DevTools:在 Profile 性能分析中显示原生 javascript 函数
迷渡
迷渡 领域专家: 前端开发技术领域 领域专家: 前端开发技术领域
博客等级 码龄19年 2405粉丝 124原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值