我已经阅读了一些有关变更检测的文章,并且所有人都说单态函数比多态函数快得多。例如,这是一个引号:
(..)这样做的原因是,必须以动态方式编写它,因此无论模型结构如何,它都可以检查每个组件。VM不喜欢这种动态代码,因为它们无法对其进行优化。它被认为是多态的,因为对象的形状并不总是相同的。Angular在运行时为每个组件创建了变化检测器类,它们是单态的,因为它们确切地知道了组件模型的形状。VM可以完美地优化此代码,这使得执行速度非常快。好处是我们不必太在乎,因为Angular会自动执行。(..)
现在,我正在尝试查找单晶与多晶的示例,但在任何地方都找不到。谁能解释这个差异,为什么会更快?
答案在于,虚拟机可以对“热功能”进行启发式检测,这意味着可以执行数百甚至数千次的代码。如果函数的执行计数超过预定限制,则VM优化器可能会选择该代码位,并尝试根据传递给函数的参数来编译优化版本。在这种情况下,假定您的函数将始终使用相同类型的参数(不一定是相同的对象)进行调用。
此原因在此v8特定的准则文档中有充分说明,其中解释了整数与一般数字优化。说您有:
function add(a, b) { return a + b; }
...而且您总是使用整数来调用此函数,此方法可能会通过编译一个在CPU上执行整数求和的函数来进行优化,这是一种快速的方法。如果在优化后将非整数值提供给它,则VM会对函数进行非优化,然后退回到未优化的版本,因为VM无法对非整数执行整数求和,并且该函数将返回错误的结果。
在指定重载单态方法的语言中,可以通过简单地编译具有不同参数签名的相同方法名称的多个版本来解决此问题,然后对其进行单独优化。这意味着您调用了不同的优化方法,因为使用不同类型的参数要求您使用不同的重载方法,因此毫无疑问您正在使用哪种方法。
您可能认为您可以在VM中保留优化功能的多个副本,并检查类型以确定要使用的优化编译功能。从理论上讲,如果方法调用之前的类型检查是免费的或非常便宜的,那将是可行的。在实践中,通常情况并非如此,您可能需要在实际代码中进行权衡,以确定最佳折衷阈值。
以下是v8特别优化的编译器的更笼统的解释(来自Google I / O 2012):
https://youtu.be/UJPdhx5zTaw?t=26m26s
简而言之:在JIT编译器中优化了一次又一次地调用相同类型的函数,因此速度更快。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句