<commit_before>---
title: \[译\] JavaScript 引擎基础：原型优化
layout: post
thread: 202
date: 2018-08-21
author: <NAME>
categories: Documents
tags: [JavaScript, 2018, 引擎, 原型, 优化, 前端]
excerpt: 本文就所有 JavaScript 引擎中常见的一些关键基础内容进行了介绍——这不仅仅局限于 V8 引擎。作为一名 JavaScript 开发者，深入了解 JavaScript 引擎是如何工作的将有助于你了解自己所写代码的性能特征。
header:
  image: ../assets/in-post/2018-08-21-Prototypes-teaser.png
  caption: "Edited from Twitter@PrimitivePic"
---

本文就所有 JavaScript 引擎中常见的一些关键基础内容进行了介绍——这不仅仅局限于 V8 引擎。作为一名 JavaScript 开发者，深入了解 JavaScript 引擎是如何工作的将有助于你了解自己所写代码的性能特征。

在[前一篇文章](https://hijiangtao.github.io/2018/06/17/Shapes-ICs/)中，我们讨论了 JavaScript 引擎是如何通过 Shapes 和 Inline Caches 来优化对象与数组的访问的。本文将介绍优化流程中的权衡与取舍，并对引擎在优化原型属性访问方面的工作进行介绍。

原文 [JavaScript engine fundamentals: optimizing prototypes](https://mathiasbynens.be/notes/prototypes)，作者 [@Benedikt](https://twitter.com/bmeurer) 和 [@Mathias](https://twitter.com/mathias)，译者 [hijiangtao](https://github.com/hijiangtao)。以下开始正文。

> 如果你倾向看视频演讲，请移步 [YouTube](https://www.youtube.com/watch?v=IFWulQnM5E0) 查看更多。

## 1. 优化层级与执行效率的取舍

[前一篇文章](https://hijiangtao.github.io/2018/06/17/Shapes-ICs/)介绍了现代 JavaScript 引擎通用的处理流程：

![](/assets/in-post/2018-08-21-Prototypes-1.svg )

We also pointed out that although the high-level pipeline is similar between engines, there are often differences in the optimization pipeline. Why is that? Why do some engines have more optimization tiers than others? It turns out there is a trade-off between quickly getting code to run, or taking some more time but eventually running the code with optimal performance.

我们也指出，尽管从高级抽象层面来看，引擎之间的处理流程都很相似，但他们在优化流程上通常都存在差异。为什么呢？**为什么有些引擎的优化层级会比其他引擎更多？**事实证明，在快速获取可运行的代码与花费更多时间获得最优运行性能的代码之间存在取舍与平衡。

![](/assets/in-post/2018-08-21-Prototypes-2.svg )

解释器可以快速生成字节码，但字节码通常效率不高。 相比之下，优化编译器虽然需要更长的时间，但最终会产生更高效的机器码。

这正是 V8 在使用的模型。V8 的解释器叫 Ignition，（就原始字节码执行速度而言）它是所有引擎中最快的解释器。V8 的优化编译器名为 TurboFan，它最终会生成高度优化的机器码。

![](/assets/in-post/2018-08-21-Prototypes-3.svg )

启动延迟与执行速度之间的这些权衡便是一些 JavaScript 引擎决定是否在流程中加入优化层的原因。例如，SpiderMonkey 在解释器和完整的 IonMonkey 优化编译器之间添加了一个 Baseline 层：

![](/assets/in-post/2018-08-21-Prototypes-4.svg )

解释器可以快速生成字节码，但字节码执行起来相对较慢。Baseline 生成代码需要花费更长的时间，但能提供更好的运行时性能。最后，IonMonkey 优化编译器花费最长时间来生成机器码，但该代码运行起来非常高效。

让我们通过一个具体的例子，看看不同引擎中的优化流程都有哪些差异。这是一些在循环中会经常重复的代码。

```javascript<commit_msg>[update post] - 2018-08-21 21:08:45<commit_after>---
title: \[译\] JavaScript 引擎基础：原型优化
layout: post
thread: 202
date: 2018-08-21
author: <NAME>
categories: Documents
tags: [JavaScript, 2018, 引擎, 原型, 优化, 前端]
excerpt: 本文就所有 JavaScript 引擎中常见的一些关键基础内容进行了介绍——这不仅仅局限于 V8 引擎。作为一名 JavaScript 开发者，深入了解 JavaScript 引擎是如何工作的将有助于你了解自己所写代码的性能特征。
header:
  image: ../assets/in-post/2018-08-21-Prototypes-teaser.png
  caption: "Edited from Twitter@PrimitivePic"
---

本文就所有 JavaScript 引擎中常见的一些关键基础内容进行了介绍——这不仅仅局限于 V8 引擎。作为一名 JavaScript 开发者，深入了解 JavaScript 引擎是如何工作的将有助于你了解自己所写代码的性能特征。

在[前一篇文章](https://hijiangtao.github.io/2018/06/17/Shapes-ICs/)中，我们讨论了 JavaScript 引擎是如何通过 Shapes 和 Inline Caches 来优化对象与数组的访问的。本文将介绍优化流程中的权衡与取舍，并对引擎在优化原型属性访问方面的工作进行介绍。

原文 [JavaScript engine fundamentals: optimizing prototypes](https://mathiasbynens.be/notes/prototypes)，作者 [@Benedikt](https://twitter.com/bmeurer) 和 [@Mathias](https://twitter.com/mathias)，译者 [hijiangtao](https://github.com/hijiangtao)。以下开始正文。

> 如果你倾向看视频演讲，请移步 [YouTube](https://www.youtube.com/watch?v=IFWulQnM5E0) 查看更多。

## 1. 优化层级与执行效率的取舍

[前一篇文章](https://hijiangtao.github.io/2018/06/17/Shapes-ICs/)介绍了现代 JavaScript 引擎通用的处理流程：

![](/assets/in-post/2018-08-21-Prototypes-1.svg )

我们也指出，尽管从高级抽象层面来看，引擎之间的处理流程都很相似，但他们在优化流程上通常都存在差异。为什么呢？**为什么有些引擎的优化层级会比其他引擎更多？**事实证明，在快速获取可运行的代码与花费更多时间获得最优运行性能的代码之间存在取舍与平衡。

![](/assets/in-post/2018-08-21-Prototypes-2.svg )

解释器可以快速生成字节码，但字节码通常效率不高。 相比之下，优化编译器虽然需要更长的时间，但最终会产生更高效的机器码。

这正是 V8 在使用的模型。V8 的解释器叫 Ignition，（就原始字节码执行速度而言）它是所有引擎中最快的解释器。V8 的优化编译器名为 TurboFan，它最终会生成高度优化的机器码。

![](/assets/in-post/2018-08-21-Prototypes-3.svg )

启动延迟与执行速度之间的这些权衡便是一些 JavaScript 引擎决定是否在流程中加入优化层的原因。例如，SpiderMonkey 在解释器和完整的 IonMonkey 优化编译器之间添加了一个 Baseline 层：

![](/assets/in-post/2018-08-21-Prototypes-4.svg )

解释器可以快速生成字节码，但字节码执行起来相对较慢。Baseline 生成代码需要花费更长的时间，但能提供更好的运行时性能。最后，IonMonkey 优化编译器花费最长时间来生成机器码，但该代码运行起来非常高效。

让我们通过一个具体的例子，看看不同引擎中的优化流程都有哪些差异。这是一些在循环中会经常重复的代码。

```javascript
{'fraction_non_alphanumeric': 0.12322611163670766, 'fraction_numerical': 0.04257332071901608, 'mean_word_length': 6.994328922495274, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 14, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '794352', 'n_tokens_mistral': 2748, 'n_tokens_neox': 2854, 'n_words': 264}