javascript 引擎_V8引擎和JavaScript优化技巧

news/2024/7/5 19:34:28

javascript 引擎

V8 is Google’s engine for compiling our JavaScript. Firefox has it’s own engine called SpiderMonkey, it’s quite similar to V8 but there are differences. We will be discussing the V8 engine in this article.

V8是Google用来编译JavaScript的引擎。 Firefox拥有自己的名为SpiderMonkey的引擎,它与V8十分相似,但也有所不同。 我们将在本文中讨论V8引擎。

A couple of facts about the V8 engine:

有关V8引擎的一些事实:

  • Written in C++ and used in Chrome and Node.js (and the newest release of Microsoft Edge)

    用C ++编写,并用于Chrome和Node.js(以及Microsoft Edge的最新版本 )

  • Implements ECMAScript as specified in ECMA-262

    实现ECMA-262中指定的ECMAScript

JavaScript之旅 (The JavaScript Journey)

So what exactly happens when we send our JavaScript to be parsed by the V8 engine (this is after it is minified, uglified and whatever other crazy stuff you do to your JavaScript code)?

那么,当我们发送要由V8引擎解析JavaScript(在将其缩小,丑化以及您对JavaScript代码执行的其他疯狂操作之后),到底发生了什么?

I’ve created the following diagram that shows all the steps, we will then discuss each step in detail:

我已经创建了显示所有步骤的下图,然后我们将详细讨论每个步骤:

In this article we’ll discuss how the JavaScript code gets parsed and how to get as much of your JavaScript to the Optimizing Compiler as possible. The Optimizing Compiler (aka Turbofan) takes our JavaScript code and converts it to high performance Machine Code, so the more code we can give it the faster our application will be. As a side note, the interpreter in Chrome is called Ignition.

在本文中,我们将讨论如何解析JavaScript代码以及如何将尽可能多JavaScript获取到Optimizing Compiler。 Optimizing Compiler(aka Turbofan )接收我们JavaScript代码并将其转换为高性能的机器代码,因此我们可以赋予它更多的代码,从而使我们的应用程序更快。 附带说明一下,Chrome中的解释器称为“ 点火器”。

解析JavaScript (Parsing JavaScript)

So the first treatment of our JavaScript code is to parse it. Let’s discuss exactly what parsing is.

因此,对我们JavaScript代码的第一种处理是对其进行解析。 让我们确切地讨论什么是解析。

There are two phases to parsing which are:

解析分为两个阶段:

  • Eager (full-parse) - this parses each line right away

    急切(完全解析) -这会立即解析每行

  • Lazy (pre-parse)- do the bare minimum, parse what we need and leave the rest until later

    懒惰(预解析) -进行最少的工作,解析我们需要的内容,然后将其余内容留到以后

Which is better? It all depends.

哪个更好? 一切都取决于。

Let’s look at some code.

让我们看一些代码。

// eager parse declarations right away
const a = 1;
const b = 2;

// lazily parse this as we don't need it right away
function add(a, b) {
  return a + b;
}

// oh looks like we do need add so lets go back and parse it
add(a, b);

So here our variable declarations will be eager parsed but then our function is lazily parsed. This is great until we get to add(a, b) as we need our add function right away so it would have been quicker to eager parse add right away.

因此,这里我们的变量声明将被eager parsed但是我们的函数将被lazily parsed 。 在我们立即add(a, b)之前,这是很棒add(a, b)因为我们需要立即add函数,因此eager parse add会更快。

To eager parse the add function right away, we can do:

为了立即eager parse add函数,我们可以执行以下操作:

// eager parse declarations right away
const a = 1;
const b = 2;

// eager parse this too
var add = (function(a, b) {
  return a + b;
})();

// we can use this right away as we have eager parsed
// already
add(a, b);

This is how most modules you use are created.

这就是您使用的大多数模块的创建方式。

功能内联 (Function Inlining)

Chrome will sometimes essentially rewrite your JavaScript, one example of this is inlining a function that is being used.

Chrome有时实际上会重写您JavaScript,其中一个示例是内联正在使用的函数。

Let’s take the following code as an example:

让我们以以下代码为例:

const square = (x) => { return x * x }

const callFunction100Times = (func) => {
  for(let i = 0; i < 100; i++) {
    // the func param will be called 100 times
    func(2)
  }
}

callFunction100Times(square)

The above code will be optimized by the V8 engine as follows:

上面的代码将通过V8引擎进行优化,如下所示:

const square = (x) => { return x * x }

const callFunction100Times = (func) => {
  for(let i = 100; i < 100; i++) {
    // the function is inlined so we don't have 
    // to keep calling func
    return x * x
  }
}

callFunction100Times(square)

As you can see from the above, V8 is essentially removing the step where we call func and instead inlining the body of square. This is very useful as it will improve the performance of our code.

从上面可以看到,V8本质上删除了我们称为func的步骤,而是内嵌了square的主体。 这非常有用,因为它将提高我们的代码的性能。

函数内联陷阱 (Function inlining gotcha)

There is a little gotcha with this approach, let’s take the following code example:

这种方法有点麻烦,让我们看下面的代码示例:

const square = (x) => { return x * x }
const cube = (x) => { return x * x * x }

const callFunction100Times = (func) => {
  for(let i = 100; i < 100; i++) {
    // the function is inlined so we don't have 
    // to keep calling func
    func(2)
  }
}

callFunction100Times(square)
callFunction100Times(cube)

So this time after we have called the square function 100 times, we will then call the cube function 100 times. Before cube can be called, we must first de-optimize the callFunction100Times as we have inlined the square function body. In cases like this, the square function will seem like it’s faster than the cube function but what is happening is the de-optimization step makes the execution longer.

因此,这一次我们调用了square函数100次之后,我们将再次调用cube函数100次。 在调用cube之前,我们必须首先对callFunction100Times进行优化,因为我们已内嵌了square函数主体。 在这种情况下, square函数似乎比cube函数快,但是发生的是去优化步骤使执行时间更长。

对象 (Objects)

When it comes to objects, V8 under the hood has a type system to differentiate your objects:

当涉及对象时,引擎盖下的V8具有用于区分您的对象的类型系统:

单态性 (Monomorphism)

The objects have the same keys with no differences.

对象具有相同的键,没有差异。

// mono example
const person = { name: 'John' }
const person2 = { name: 'Paul' }

多态性 (Polymorphism)

The objects share a similar structure with some small differences.

这些对象共享相似的结构,但有一些细微差别。

// poly example
const person = { name: 'John' }
const person2 = { name: 'Paul', age: 27 }

巨形 (Megamorphism)

The objects are entirely different and cannot be compared.

对象完全不同,无法比较。

// mega example
const person = { name: 'John' }
const building = { rooms: ['cafe', 'meeting room A', 'meeting room B'], doors: 27 }

So now we know the different objects in V8, let’s see how V8 optimizes our objects.

现在我们了解了V8中的不同对象,让我们看看V8如何优化我们的对象。

隐藏的课程 (Hidden classes)

Hidden classes are how V8 identifies our objects.

隐藏类是V8识别我们的对象的方式。

Let’s break this down into steps.

让我们将其分解为几个步骤。

We declare an object:

我们声明一个对象:

const obj = { name: 'John'}

V8 will then declare a classId for this object.

然后,V8将为此对象声明一个classId

const objClassId = ['name', 1]

Then our object is created as follows:

然后我们的对象创建如下:

const obj = {...objClassId, 'John'}

Then when we access the name property on our object like so:

然后,当我们像这样访问对象的name属性时:

obj.name

V8 does the following lookup:

V8执行以下查询:

obj[getProp(obj[0], name)]

This is process V8 goes through when creating our objects, now let’s see how we can optimize our objects and reuse classIds.

V8是创建对象时经历的过程,现在让我们看看如何优化对象classIdsclassIds

创建对象的技巧 (Tips for Creating Objects)

If you can, you should declare your properties in the constructor. This will ensure the object structure stays the same so V8 can then optimize your objects.

如果可以的话,应该在构造函数中声明属性 。 这样可以确保对象结构保持不变,因此V8可以优化您的对象。

class Point {
  constructor(x,y) {
    this.x = x
    this.y = y
  }
}

const p1 = new Point(11, 22) // hidden classId created
const p2 = new Point(33, 44)

You should keep the property order constant, take the following example:

您应该使属性顺序保持不变 ,以以下示例为例:

const obj = { a: 1 } // hidden class created
obj.b = 3

const obj2 = { b: 3 } // another hidden class created
obj2.a = 1

// this would be better
const obj = { a: 1 } // hidden class created
obj.b = 3

const obj2 = { a: 1 } // hidden class is reused
obj2.b = 3

常规优化技巧 (General Optimization Tips)

So now let’s get into some general tips that will help your JavaScript code be better optimized.

因此,现在让我们进入一些通用技巧,这些技巧将帮助您更好地优化JavaScript代码。

修复函数参数类型 (Fix function argument types)

When arguments are being passed to a function it’s important they are the same type. Turbofan will give up trying to optimize your JavaScript after 4 tries if the argument types are different.

将参数传递给函数时,重要的是它们必须是同一类型。 如果参数类型不同,Turbofan将在尝试4次后放弃尝试优化JavaScript。

Take the following example:

请看以下示例:

function add(x,y) {
  return x + y
}

add(1,2) // monomorphic
add('a', 'b') // polymorphic
add(true, false)
add({},{})
add([],[]) // megamorphic - at this stage, 4+ tries, no optimization will happen

Another tip is to make sure to declare classes in the global scope:

另一个技巧是确保在全局范围内声明类

// don't do this
function createPoint(x, y) {
  class Point {
    constructor(x,y) {
      this.x = x
      this.y = y
    }
  }

  // new point object created every time
  return new Point(x,y)
}

function length(point) {
  //...
}

结论 (Conclusion)

So I hope you learned a few things about how V8 works under the hood and how to write better optimized JavaScript code.

因此,我希望您了解了V8的工作原理以及如何编写更好的优化JavaScript代码的一些知识。

翻译自: https://www.digitalocean.com/community/tutorials/js-v8-engine

javascript 引擎


http://www.niftyadmin.cn/n/3649561.html

相关文章

Widget的基本知识与历史渊源

一、Widget是什么&#xff1f; App Widget是应用程序窗口小部件&#xff08;Widget&#xff09;是微型的应用程序视图&#xff0c;它可以被嵌入到其它应用程序中&#xff08;比如桌面&#xff09;并接收周期性的更新。你可以通过一个App Widget Provider来发布一个Widget。…

华为云青年开发班:黑白棋游戏开发

放假回家第一天&#xff0c;继续肝&#xff01;写一篇博客证明我还在&#xff01; 实验成果 任何时候都不要放弃自己的梦想&#xff0c;也许下一刻&#xff0c;梦想就会成真了呢&#xff01;

[论道]Sales职业生涯规划 作者:李楠

Sales职业生涯规划 作者&#xff1a;SPN睿商在线-李楠- 2005-08-02 聪明的Sales了解自己的职业生涯发展方向&#xff0c;知道自己适合做哪种类型的销售……讲述者和推销者 讲述型的Sales只会倾倒&#xff0c;推销型的Sales会洞察客户需求…… 孙&#xff1a;最近看了一本《竞争…

用switch语句编写程序_如何在Go中编写switch语句

用switch语句编写程序介绍 (Introduction) Conditional statements give programmers the ability to direct their programs to take some action if a condition is true and another action if the condition is false. Frequently, we want to compare some variable again…

桌面widget详解(一)——基本demo构建

前言&#xff1a;这段时间真的是有点堕落了&#xff0c;没怎么看书&#xff0c;项目也做的乱七八糟&#xff0c;基本没什么长进&#xff0c;好像男人也有生理期一样&#xff0c;每个月总有那么几天提不起精神&#xff0c;等自己彻底感到罪恶感的时候再重新整装前行。这几天做桌…

[Wap] 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果

[Wap] 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果编写者日期关键词郑昀ultrapower2005-8-18Wap ASP.NET Mobile control device adapter自定义的mobile.List的横排效果现有的mobile.List输出效果&#xff0c;每一个Item之间一定会换行&#xff0c;如果你看了Wml…

华为云微认证考试简介

我最近参加了华为云的微认证考试&#xff0c;并且成功的拿到了证书&#xff0c;所以分享一下华为云微认证考试 什么是微认证&#xff1f; 华为云微认证是基于线上学习与在线实践&#xff0c;快速获得场景化技能提升的认证。华为云微认证官网 华为云微认证视频介绍 华为云微认…

Android XUtils 框架简介

xUtils简介 xUtils 包含了很多实用的android工具。xUtils 源于Afinal框架&#xff0c;对Afinal进行了大量重构&#xff0c;使得xUtils支持大文件上传&#xff0c;更全面的http请求协议支持&#xff0c;拥有更加灵活的ORM&#xff0c;更多的事件注解支持且不受混淆影响...xUitl…