首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么JavaScript中存在单形和多态物质?

为什么JavaScript中存在单形和多态物质?
EN

Stack Overflow用户
提问于 2016-05-05 19:20:08
回答 2查看 5.7K关注 0票数 26

我读过一些关于变化检测的文章,他们都说单形函数比多态函数快得多。例如,这里有一段引语:

(.)原因是,它必须以动态的方式编写,因此它可以检查每个组件,不管它的模型结构是什么。VMs不喜欢这种动态代码,因为它们无法优化它。它被认为是多态的,因为对象的形状并不总是相同的。角在运行时为每个组件创建变化检测器类,它们是单形的,因为它们确切地知道组件模型的形状。VMs可以完美地优化这段代码,这使得它执行起来非常快。好的是我们不必太在意这个,因为角是自动完成的。

来源

现在,我试着找出单曲和多态的例子,但是哪里都找不到。有谁能解释一下这种差异,为什么它更快?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-05 19:48:04

答案在于VM可以对“热函数”进行启发式检测,这意味着代码被执行了数百次甚至数千次。如果函数的执行次数超过了预定的限制,VM优化器可能会获取该代码,并尝试根据传递给该函数的参数编译优化版本。在这种情况下,它假定函数将始终使用相同类型的参数(不一定是相同的对象)调用。

这种情况的原因在这个V8-特定指导文件中有很好的说明,其中解释了整数与一般数字优化的关系。说你有:

代码语言:javascript
复制
function add(a, b) { return a + b; }

...and --你总是用整数来调用这个函数,这个方法可能会通过编译一个在CPU上进行整数求和的函数来优化,这是非常快速的。如果在优化之后给它提供一个非整数值,那么VM就去优化函数并返回到未优化的版本,因为它不能对非整数执行整数求和,并且函数会返回错误的结果。

在指定重载单形方法的语言中,可以通过编译具有不同参数签名的相同方法名称的多个版本来解决这一问题,然后对其进行优化。这意味着调用不同的优化方法,因为使用不同类型的参数需要使用不同的重载方法,所以您使用的方法没有问题。

您可能认为可以在VM中保留多个优化函数的副本,并检查类型以确定要使用的优化编译函数。理论上,如果方法调用之前的类型检查是免费的或非常便宜的,那么这是可行的。在实践中,通常情况并非如此,您可能希望平衡现实世界的代码,以确定最佳的权衡阈值。

这里有一个更一般化的解释,特别是V8的优化编译器(来自Google /O 2012):

https://youtu.be/UJPdhx5zTaw?t=26m26s

简而言之,:在JIT编译器中一次又一次地调用相同类型的函数是优化的,因此速度更快。

票数 24
EN

Stack Overflow用户

发布于 2016-05-05 20:04:41

据我所知,单形是一个非常罕见的术语。我个人从未听说过它用于编码。为了弄清楚什么是单态,我认为我们可以通过观察多态性是什么来推断它的含义。

多态:是指许多(多个)不同的对象可以用相同的类型表示到机器/运行时/解释器。例如,在C#中,您可能有任意数量的实现ICloneable的类,其中任何类都可以在泛型链接列表的复制构造函数中使用(例如)。如果您有兴趣的话,这里有完整的未经测试的类作为示例

那么,单形是什么意思呢?

对我来说,单形意味着对象的解释器处理它所期望的确切类型,而对预期类型的继承或修改是不可能的。在这种情况下,使用鸭子类型的javascript语言,VM表示“这个javascript对象具有这些精确的属性,这些属性属于这些精确的类型,并命名为,与它们完全相同”。在C#中,如果我们想成为单形的,那么泛型类型限制将是不可能的,因为T必须始终是相同的类型。

这个链接提供了一个很好的指南,说明为什么这对性能很重要。对我来说,这可以概括如下。

Javascript引擎希望避免查找属性的表,而不是做对象指针偏移。对于一元形式,给定代码行中对象的偏移量总是相同的,VM很容易找到如何使用指针加法而不是表查找来执行查找。

实际上,引擎试图处理传递给同一个函数的少量不同对象,但是如果对象在同一代码行上看起来总是相同的话,VM将是最快的。

清晰的例子

下面的示例是有效的javascript,但是函数f1的参数f1不是单形的,因为VM需要处理传入的两个不同形状的对象。

代码语言:javascript
复制
function f1(o) {
  console.log(o.prop1)
  console.log(o.prop2)
}

// ...

o1 = { prop1: 'prop1', prop2: 'prop2' }
o2 = { prop1: 'prop1', prop2: 'prop2', prop3: 'prop3' }

f1(o1)
f1(o2)

您提供的链接中引用的要点是,开箱即用的AngularJS提供了代码,使其所有的javascript函数参数都是“单形的”,因为每次调用传入它们的对象都有相同的结构。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37058643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档