简体   繁体   English

lodash“get”和“if else”子句之间的性能差异

[英]Performance difference between lodash “get” and “if else” clauses

Let's say you have a typescript object, where any element can be undefined . 假设您有一个打字稿对象,其中任何元素都可以是undefined If you want to access a heavily nested component, you have to do a lot of comparisons against undefined . 如果要访问重度嵌套的组件,则必须对undefined进行大量比较。

I wanted to compare two ways of doing this in terms of performance: regular if-else comparisons and the lodash function get . 我想比较两种在性能方面做到这一点的方法:常规if-else比较和lodash函数get

I have found this beautiful tool called jsben were you can benchmark different pieces of js code. 我发现这个名为jsben的漂亮工具你可以对不同的js代码进行基准测试。 However, I fail to interpret the results correctly. 但是,我无法正确解释结果。

In this test , lodash get seems to be slightly faster. 在这个测试中 ,lodash get似乎稍快一些。 However, if I define my variable in the Setup block (as opposed to the Boilerplate code ), the if-else code is faster by a wide margin. 但是, 如果我在Setup block定义我的变量 (而不是Boilerplate code ),那么if-else代码的速度会更快。

What is the proper way of benchmarking all this? 对所有这些进行基准测试的正确方法是什么? How should I interpret the results? 我该如何解释结果呢? Is get so much slower that you can make argument in favour of if-else clauses, in spite of the very poor readability? get这么多慢就可以使论点赞成if-else子句,尽管非常贫穷的可读性?

I think you're asking the wrong question. 我想你问的是错误的问题。

First of all, if you're going to do performance micro-optimization (as opposed to, say, algorithmic optimization), you should really know whether the code in question is a bottleneck in your system. 首先,如果您要进行性能微优化(而不是算法优化),您应该真正了解相关代码是否是系统中的瓶颈。 Fix the worst bottlenecks until your performance is fine, then stop worrying overmuch about it. 解决最糟糕的瓶颈,直到你的表现很好,然后不要再担心它了。 I'd be quite surprised if variation between these ever amounted to more than a rounding error in a serious application. 如果在严重的应用程序中这些差异超过舍入误差,我会感到非常惊讶。 But I've been surprised before; 但我以前一直很惊讶; hence the need to test . 因此需要测试

Then, when it comes to the actual optimization, the two implementations are only slightly different in speed, in either configuration. 然后,当涉及到实际优化时,两种实现在两种配置中的速度都略有不同。 But if you want to test the deep access to your object, it looks as though the second one is the correct way to think about it. 但是如果你想测试对你的对象的深层访问,看起来第二个是正确的思考方式。 It doesn't seem as though it should make much difference in relative speeds, but the first one puts the initialization code where it will be "executed before every block and is part of the benchmark." 它似乎不应该在相对速度上有很大的不同,但是第一个将初始化代码放在“在每个块之前执行并且是基准测试的一部分”的地方。 The second one puts it where "it will be run before every test, and is not part of the benchmark." 第二个是“它将在每次测试之前运行,而不是基准测试的一部分”。 Since you want to compare data access and not data initialization, this seems more appropriate. 由于您想要比较数据访问而不是数据初始化,这似乎更合适。

Given this, there seems to be a very slight performance advantage to the families && families.Trump && families.Trump.members && ... technique. 鉴于此, families && families.Trump && families.Trump.members && ...似乎有一个非常轻微的性能优势。 families && families.Trump && families.Trump.members && ...技术。 (Note: no if s or else s in sight here!) (注:没有if S或else在望这儿!)

But is it worth it? 但是这值得吗? I would say not. 我会说不。 The code is much, much uglier. 代码非常多,更加丑陋。 I would not add a library such as lodash (or my favorite, Ramda ) just to use a function as simple as this, but if I was already using lodash I wouldn't hesitate to use the simpler code here. 我不会添加库等lodash(或我的最爱, Ramda )只用这样简单的功能,但如果我已经使用lodash我会毫不犹豫地在这里使用简单的代码。 And I might import one from lodash or Ramda, or simply write my own otherwise, as it's fairly simple code. 我可以从lodash或Ramda导入一个,或者只是自己编写,因为它是相当简单的代码。

That native code is going to be faster than more generic library code shouldn't be a surprise. 该本机代码将比更通用的库代码更快不应该是一个惊喜。 It doesn't always happen, as sometimes libraries get to take shortcuts that the native engine cannot, but it's likely the norm. 它并不总是会发生,因为有时库会采用本机引擎无法获得的快捷方式,但它很可能是常态。 The reason to use these libraries rarely has to do with performance, but with writing more expressive code. 使用这些库的原因很少与性能有关,而是编写更具表现力的代码。 Here the lodash version wins, hands-down. 在这里,lodash版本赢得了胜利。

What is the proper way of benchmarking all this? 对所有这些进行基准测试的正确方法是什么?

Only benchmark the actual code you are comparing, move as much as possible outside of the tested block. 仅对您要比较的实际代码进行基准测试,尽可能在测试块之外移动。 Run every of the two pieces a few (hundred) thousand times, to average out the influence of other parts. 将这两件中的每一件运行几百(一万)次,以平均其他部件的影响。

How should I interpret the results? 我该如何解释结果呢?

1) check if they are valid: 1)检查它们是否有效:

Do the results fit your expectation? 结果是否符合您的期望? If not, could there be a cause for that? 如果没有,是否有原因? Does the testcase replicate your actual usecase? 测试用例是否复制了您的实际用例?

2) check if the result is relevant: 2)检查结果是否相关:

How does the time it takes compare to the actual time in your usecase? 与用例中的实际时间相比,它需要的时间如何? If your code takes 200ms to load, and both tests run in under ~1ms, your result doesnt matter. 如果您的代码需要200ms加载,并且两个测试都在~1ms内运行,那么您的结果无关紧要。 If you however try to optimize code that runs 60 times per second, 1ms is already a lot. 但是,如果您尝试优化每秒运行60次的代码,则1ms已经很多了。

3) check if the result is worth the work 3)检查结果是否值得工作

Often you have to do a lot of refactoring, or you have to type a lot, does the performance gain outweight the time you invest? 通常你需要进行大量的重构,或者你必须输入很多,你投资的时候性能会增加吗?

Is get so much slower that you can make argument in favour of if-else clauses, in spite of the very poor readability? 尽管可读性非常差,但是你可以加快if-else子句的争论吗?

I'd say no. 我会说不。 use _.get (unless you are planning to run that a few hundred times per second). 使用_.get (除非你计划每秒运行几百次)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM