2020-02-16 Javascript引擎和运行时堆栈

Javascript引擎和运行时堆栈

  1. V8引擎的两个主要组件


    V8
    • Memory Heap 内存堆 ——  这是内存分配发生的地方
    • Call Stack 调用堆栈 ——  这是在你代码执行时栈帧存放的位置
  2. Runtime运行时

    • 由浏览器所提供的称为 Web API 的东西,比如 DOM、AJAX、setTimeout 等等。
    • 然后,我们还有非常流行的事件循环和回调队列。
  3. 调用堆栈

    • JavaScript 是一种单线程编程语言,这意味着它只有一个 Call Stack 。因此,它一次仅能做一件事。
    • Call Stack 是一个数据结构,它基本上记录了我们在程序中的所处的位置。如果我们进入一个函数,我们把它放在堆栈的顶部。如果我们从一个函数中返回,我们弹出堆栈的顶部。这是所有的堆栈可以做的东西。
    • 代码分析
      function multiply(x, y) {
          return x * y;
      }
      function printSquare(x) {
          var s = multiply(x, x);
          console.log(s);
      }
      printSquare(5);
      
      调用栈
  • 在某些情况下,调用堆栈中函数调用的数量超出了调用堆栈的实际大小,浏览器通过抛出一个错误


    image
  1. 并发&事件循环
    • 如果在调用堆栈中执行的函数调用需要花费大量时间才能进行处理,会发生什么?
      • 问题是,虽然调用堆栈有要执行的函数,浏览器实际上不能做任何事情 - 它被阻塞了。这意味着浏览器无法渲染,它不能运行任何其他代码,它就是被卡住了。如果你想在你的应用程序中使用流畅的 UI ,这就会产生问题。
    • 如何执行大量代码而不阻塞 UI 使得浏览器无法响应? 解决方案就是异步回调。

V8引擎优化

  1. JavaScript 引擎是执行 JavaScript 代码的程序或解释器。 JavaScript 引擎可以作为标准解释器或即时编译器,它以某种形式将 JavaScript 编译为字节码。

  2. V8 最初是被设计用来提高网页浏览器内部 JavaScript 执行的性能。为了获得更快的速度,V8 将 JavaScript 代码翻译成更高效的机器代码,而不是使用解释器来翻译代码。它通过使用 JIT(Just-In-Time)编译器(如 SpiderMonkey 或 Rhino(Mozilla)等许多现代 JavaScript 引擎)来将 JavaScript 代码编译为机器代码。 这里的主要区别在于 V8 不生成字节码或任何中间代码。

  3. 垃圾清理
    V8 使用了渐进式标记:而不是走遍整个堆内容,试图标记每一个可能的对象。它只走一部分堆内容,然后恢复正常执行。下一个 GC 将从先前堆走过的地方继续执行。这允许在正常执行期间非常短的暂停。

  4. 如何编写优化的javascript

    • 对象属性的顺序:始终以相同的顺序实例化对象属性,以便共享的隐藏类和随后优化的代码可以共享之。

    • 动态属性:在实例化之后向对象添加属性将强制执行隐藏的类更改,并降低之前隐藏类所优化的所有方法的执行速度。相反,在其构造函数中分配所有对象的属性。

    • 方法:重复执行相同方法的代码将比仅执行一次的多个不同方法(由于内联缓存)的代码运行得更快。

    • 数组:避免稀疏数组,其中键值不是自增的数字。并没有存储所有元素的稀疏数组是哈希表。这种数组中的元素访问开销较高。另外,尽量避免预分配大数组。最好是按需增长。最后,不要删除数组中的元素。这会使键值变得稀疏。

    • 标记值:V8 使用 32 位表示对象和数值。由于数值是 31 位的,它使用了一位来区分它是一个对象(flag = 1)还是一个称为 SMI(SMall Integer)整数(flag = 0)。那么,如果一个数值大于 31 位,V8会将该数字装箱,把它变成一个双精度数,并创建一个新的对象来存放该数字。尽可能使用 31 位有符号数字,以避免对 JS 对象的高开销的装箱操作。

你可能感兴趣的:(2020-02-16 Javascript引擎和运行时堆栈)