Facebook 推出 Hermes: JavaScript engine optimized for mobile apps

2019-07-14 admin

Mobile applications are growing larger and more complex. Larger apps using JavaScript frameworks often experience performance issues as developers add features and complexity. These issues are generated from various spots, but the people using these apps expect them to run smoothly, regardless of the device they are on.

To increase the performance of Facebook’s apps, we have teams that continuously improve our JavaScript code and platforms. As we analyzed performance data, we noticed that the JavaScript engine itself was a significant factor in startup performance and download size. With this data in hand, we knew we had to optimize JavaScript performance in the more constrained environments of a mobile phone compared with a desktop or laptop. After exploring other options, we built a new JavaScript engine we call Hermes. It is designed to improve app performance, focusing on our React Native apps, even on mass-market devices with limited memory, slow storage, and reduced computing power.

At Chain React 2019, we announced the Hermes JavaScript engine. We have open-sourced the Hermes engine, as well as integration with Hermes for React Native. We are excited to work with the open source community and have developers start using Hermes today.

How Hermes improves React Native performance

For JavaScript-based mobile applications, user experience benefits from attention to a few primary metrics:

  • The time it takes for the app to become usable, called time to interact (TTI)
  • The download size (on Android, APK size)
  • Memory utilization

Metrics for MatterMost React Native app running on a Google Pixel, similar in performance to popular phones in markets like India.

<figcaption id=“caption-attachment-13264”>Metrics for MatterMost React Native app running on a Google Pixel, similar in performance to popular phones in markets like India.</figcaption>

Notably, our primary metrics are relatively insensitive to the engine’s CPU usage when executing JavaScript code. Focusing on these metrics leads to strategies and trade-offs that differ from most existing JavaScript engines today. Consequently, our team designed and built Hermes from scratch. As a result of this focus, our implementation provides substantial improvement for React Native applications.

Because Hermes is optimized for mobile apps, we do not have plans to integrate it with any browsers or with server infrastructure such as Node.js. Existing JavaScript engines remain preferable in those environments.

Key Hermes architectural decisions

Mobile device limitations, such as smaller amounts of RAM and slower flash, led us to make certain architectural decisions. To optimize for this environment, we implemented the following:

Bytecode precompilation

Commonly, a JavaScript engine will parse the JavaScript source after it is loaded, generating bytecode. This step delays the start of JavaScript execution. To skip this step, Hermes uses an ahead-of-time compiler, which runs as part of the mobile application build process. As a result, more time can be spent optimizing the bytecode, so the bytecode is smaller and more efficient. Whole-program optimizations can be performed, such as function deduplication and string table packing.

The bytecode is designed so that at runtime, it can be mapped into memory and interpreted without needing to eagerly read the entire file. Flash memory I/O adds significant latency on many medium and low-end mobile devices, so loading bytecode from flash only when needed and optimizing bytecode for size leads to significant TTI improvements. In addition, because the memory is mapped read-only and backed by a file, mobile operating systems that don’t swap, such as Android, can still evict these pages under memory pressure. This reduces out-of-memory process kills on memory constrained devices.

Hermes: An open source JavaScript engine optimized for mobile apps, starting with React Native

Although compressed bytecode is a bit larger than compressed JavaScript source code, because Hermes’s native code size is smaller, Hermes decreases overall application size for Android React Native apps.

No JIT

To speed execution, most widely used JavaScript engines can lazily compile frequently interpreted code to machine code. This work is performed by a just-in-time (JIT) compiler.

Hermes today has no JIT compiler. This means that Hermes underperforms some benchmarks, especially those that depend on CPU performance. This was an intentional choice: These benchmarks are generally not representative of mobile application workloads. We have done some experimentation with JITs, but we believe that it would be quite challenging to achieve beneficial speed improvements without regressing our primary metrics. Because JITs must warm up when an application starts, they have trouble improving TTI and may even hurt TTI. Also, a JIT adds to native code size and memory consumption, which negatively affects our primary metrics. A JIT is likely to hurt the metrics we care about most, so we chose not to implement a JIT. Instead, we focused on interpreter performance as the right trade-off for Hermes.

Garbage collector strategy

On mobile devices, efficient use of memory is especially important. Lower-end devices have limited memory, OS swapping does not generally exist, and operating systems aggressively kill applications that use too much memory. When apps are killed, slow restarts are required and background functionality suffers. In early testing, we learned that virtual address (VA) space, especially contiguous VA space, can be a limited resource in large applications on 32-bit devices even with lazy allocation of physical pages.

To minimize memory and VA space used by the engine, we have built a garbage collector with the following features:

  • On-demand allocation: Allocates VA space in chunks only as needed.
  • Noncontiguous: VA space need not be in a single memory range, which avoids resource limits on 32-bit devices.
  • Moving: Being able to move objects means memory can be defragmented and chunks that are no longer needed are returned to the operating system.
  • Generational: Not scanning the entire JavaScript heap every GC reduces GC times.

Developer experience

To start using Hermes, developers will need to make a few changes to their build.gradle files and recompile the app. See the full instructions for the migration to use Hermes on React Native.

 project.ext.react = [
  entryFile: "index.js",
  enableHermes: true
]

Lazy compilation

Iteration speed is one of the main benefits of a JavaScript-based platform, but compiling bytecode in advance would chip away at this advantage. To keep reloads fast, Hermes debug builds don’t use ahead-of-time compilation; instead, they generate bytecode lazily on device. This allows for rapid iteration using Metro or another source of plain JavaScript code to run. The trade-off is that lazy-compiled bytecode does not include all the optimizations of a production build. In practice, although we can measure the difference in performance, we have found this approach is sufficient to provide a good developer experience without affecting production metrics.

Standards-compliant

Hermes currently targets the ES6 specification, and we intend to keep current with the JavaScript specification as it evolves. To keep the engine’s size small, we have chosen not to support a few language features that do not appear to be commonly used in React Native apps, such as proxies and local eval(). A complete list can be found at our GitHub.

Debugging

To provide a great debugging experience, we implemented support for Chrome remote debugging via the DevTools protocol. Until today, React Native has supported debugging using only an in-app proxy to run the application JavaScript code in Chrome. This support made it possible to debug apps, but not synchronous native calls in the React Native bridge. Support for the remote debugging protocol allows developers to attach to the Hermes engine running on their device and debug their applications natively, using the same engine as in production. We are also looking into implementing additional support for the Chrome DevTools protocol besides debugging.

Hermes developer view

Enabling improvements to React Native

To ease migration efforts to Hermes and continue supporting JavaScriptCore on iOS, we built JSI, a lightweight API for embedding a JavaScript engine in a C++ application. This API has made it possible for React Native engineers to implement their own infrastructure improvements. JSI is used by Fabric, which allows for preemption of React Native rendering, and by TurboModules, which allow for lighter weight native modules that can be lazy loaded as needed by a React Native application.

React Native was our initial use case and has informed much of our work to date, but we aren’t stopping there. We intend to build time and memory profiling tools to make it easier for developers to improve their applications. We would like to fully support the Visual Studio Code debugger protocol, including completion and other features not available today. We’d also like to see other mobile use cases.

No open source project can be successful without engagement from the community. We’d love for you to try Hermes in your React Native apps, see how it works, and help us make Hermes better for everyone. We are especially interested in seeing which use cases the community finds useful, both inside and outside of React Native.

We’d like to thank Tzvetan Mikov, Will Holen, and the rest of the Hermes team for their work to build and open-source Hermes.

[转载]原文链接:https://code.fb.com/android/hermes/

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-69698.html

文章标题:Facebook 推出 Hermes: JavaScript engine optimized for mobile apps

相关文章
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
javascript是什么意思
avaScript是Netscape开发的一个对象脚本语言,它使用在世界各地数以百万计的网页和服务器应用程序上。 网景的JavaScript是ecma - 262版的标准脚本语言,和公布的标准只有轻微的差异。 与广为流行的错误理解相反,Ja...
2015-11-12
21天学通javascript
简介: 本书是Javascript入门教程。Javascript是Web开发中应用最早、发展最成熟、用户最多的脚本语言。其语法简洁,代码可读性在众多脚本语言中最好,它在使用时不用考虑数据类型,是真正意义上的动态语言。本书总分为四篇,共21章...
2015-11-16
React Native v0.13.3 发布,Facebook开源框架
React is a JavaScript library for building user interfaces. Just the UI: Lots of people use React as the V in MVC. Since...
2015-11-12
JavaScript的组成
一个完整的JavaScript由3个部分组成:核心(ECMAScript) 文档对象模型(DOM) 浏览器对象模型(BOM) ECMAScript 描述了该语言的语法和基本对象 ; DOM 描述了处理网页内容的方法和接口 ; BOM 描...
2015-11-12
javaScript+turn.js实现图书翻页效果实例代码
为了实现图书翻页的效果我们在网上可以看到很多教程 在这里推荐turn.js 网上的turn.js 有api 不过是英文的  很多人看起来不方便 .关于代码也是奇形怪状在这里我将详细讲解如何使用turn.js实现翻页效果 ,本篇文章只是讲解 ...
2017-03-16
JavaScript 事件流、事件处理程序及事件对象总结
JS与HTML之间的交互通过事件实现。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用监听器(或处理程序)来预定事件,以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式,支持页面的行为与页面的外观之间的松散耦合。...
2017-04-05
Facebook发布React Native!
React.js Conf 2015会议上,Facebook发布了React Native。 React.js 是 Facebook 推出的一个用来构建用户界面的 JavaScript 库。 React中,把一切东西都看成组件,而且所有组件...
2015-11-12
JavaScript变量的声明
声明变量 变量在脚本中的首次亮相是在其声明中。 在变量首次出现时将会在内存中设置它,因此您稍后可在脚本中引用它。 应在使用变量之前先声明变量。 可以使用 var 关键字实现此目的。 &lt;span id=“mt9” class=“sent...
2015-11-12
JavaScript短路原理精简代码
js中||和&amp;&amp;的特性帮我们精简了代码的同时,也带来了代码可读性的降低,虽然高效,但请灵活使用。 在js逻辑运算中,0、&quot;&quot;、null、false、undefined、NaN都会判为false,其他都为t...
2015-11-12
回到顶部