Hacker News new | past | comments | ask | show | jobs | submit login
Hermes – A small JavaScript engine optimized for running React Native on Android (github.com)
207 points by smoser 5 days ago | hide | past | web | favorite | 56 comments





I understand and accept the reality of path dependence.

At the same time, when I see projects like his, V8, HHVM, etc. I can't help but wonder where we could be if all of that engineering effort had gone into more carefully-designed languages.


I mean Lua[1] exists, predates Javascript[2], is incredibly fast[3] and can be easily embedded[4]. I've personally shipped production game titles where the whole game state + logic was inside a 400kb block on a PSP where you only had 8MB of system ram, and this was before LuaJIT.

Sadly, developer familiarity and ecosystem/mindshare sometimes dominate technical constraints, at least that's how we ended up with Javascript everywhere.

[1] https://en.wikipedia.org/wiki/Lua_(programming_language)

[2] https://en.wikipedia.org/wiki/JavaScript

[3] https://luajit.org/

[4] https://github.com/vvanders/wasm_lua


It's a perfectly valid sentiment but... Comments like this annoy me because, as I get older (turned 40 this year surpassing 20 years of web development) I've noticed variants of it come up many times a year in various contexts and it often feels like so much useless hand wringing and lamenting. In my experience shoulda, coulda, wouldas will get you bupkis in this world. Kinda like how a great idea is worth pretty much nothing.

The problem is much bigger than the design of a language, the problem is producing something (not a language) people will use and growing software systems that meet varying demands as those products evolve in a way that is affordable. Of course there are all sorts of tradeoffs to make these things happen, most of which have nothing to do with idealized whiteboarding and language design. That stuff often irrelevant when you take into consideration all the various kinds of other situation-specific details people face to make things lots of people use.

That goes the same for products and for languages. And of course the two classes of processes co-evolve. Further, language design does not imply better products. It is tangential to all the other things that make a product happen. You have to hire good people, you have to identify meaningful problems and provide better solutions. You have to get it in front of people and you have to adapt over time to your core audience's needs. Use lua use php use C# whatever you do all your choices including that one need to be self supporting of each other. The developers have experience in x, y is what runs on the platform, devs more often know a than b and so are cheaper to find. Language design matters not in those scenarios.

Not defending any language design or any technical choices over others here at all, just saying if you want to see a change in the state of things sentiments like this are more like eating popcorn while you watch the world go by. Kind of like when you have an open source project and get requests for fixes but no pull requests. The most viable open source is build by a community of collaborators and is easy for new collaborators to join in and contribute to. If you don't have a community of users that care about your project it does not matter what technical decisions you make, what language you use and what design it follows.

So what matters more than language design is problem solving and community and getting more pull requests than the other guy, more conversions than the other app and shoulda, coulda, wouldas are popcorn on the theater floor.


> it often feels like so much useless hand wringing and lamenting.

Not every comment on the Internet needs to be actionable, but sure.

> Further, language design does not imply better products.

That's fair, but we aren't talking about products here. We're talking about an announcement of a language implementation. Jazz records won't cure cancer, but that doesn't mean we can't talk about jazz.

Not defending any language design or any technical choices over others here at all, just saying if you want to see a change in the state of things sentiments like this are more like eating popcorn while you watch the world go by.

My day job is working on a language, for what it's worth, so I can both eat popcorn and work to change the state of things.


This is what I always go back to. We have so many smart engineers working on ways to interpret JS to interact with native components and try to tighten that loop to make it faster. Why is there not a large movement to just make UI development in native languages better? Like, Swift UI looks great but it appears to be a huge exception to what everyone else wants to do.

I'd love to see more work go towards making cross platform UI easier to do in native languages. I feel like you could get a lot more mileage out of that, especially if you add WASM as a compilation target, then you can get the same ubiquity that JS has.


> Why is there not a large movement to just make UI development in native languages better

What are these native languages you speak of?


> What are these native languages you speak of?

Really any of them. Swift UI is the only example I can think of where a group of folks are working on making UI easy and intuitive to create and manage inside of a native language.

Why is there not an effort to make something as intuitive in C++ or GO or Rust? C++ would probably be the hardest one, sure, and there are many UI frameworks for all of these languages but none of them are as simple or intuitive as Swift UI or how React / Vue works inside of JS.

I'd love to see some more experimentation in ways of building UI in native languages. Heck, even in managed languages like C# or Java they could use the same type of treatment.


There are probably more JavaScript developers (not necessarily professional developers, just people writing JavaScript) than C++, Go and Rust combined, so it's just more likely that the ecosystem with more momentum will get more interest and resources.

I'm sure Facebook could have written React Native in C, C++, Go, Java or Rust, but take a guess at what the adoption rate and the hype around it would have been...

If Netscape/MS browser in the 90s had shipped with an embedded, sandboxed JVM with native browser APIs, then maybe the world would be very different today, but we work with what we have don't we all?


Every language involves tradeoffs. The initial JS tradeoffs were ok for the target audience and environments. A "carefully-designed language" in 2019 might hold up for 2019 use cases but we don't know whether the tradeoffs will make sense in 2029

This is generally true. Most languages were carefully designed and if they are disliked now, it's mainly because we've forgotten their original constraints in which the language's design made sense. (For example, header files in C are a reasonable approach when your compiler can't fit an entire source file in memory.)

But JS and PHP aren't that. They both have a lot of good ideas in them but they are also both hampered by lots of initial mistakes in their design. JS because it was designed so quickly, PHP because it was cobbled together ad-hoc by someone who wasn't focused on the design of the language.

Semicolon insertion in JS doesn't represent a smart trade-off from the past, it was just a bad design whose author didn't have time to fix it before it hit the marketplace [0]. Likewise, PHP's wildly inconsistent core library names aren't a sign of some thoughtful hidden order. They're because Rasmus lazily used strlen() as the hash function for strings and wanted them to go into different buckets [0].

[0]: https://brendaneich.com/2012/04/the-infernal-semicolon/

[1]: https://news-web.php.net/php.internals/70691


Can't we be reasonably sure it will be better than a weekend spitball? (The most successful spitball of all time to give due credit)

There's always skip http://www.skiplang.com/

> Skip is an experimental programming language developed at Facebook from 2015-2018.


https://github.com/skiplang/skip

> The Skip project concluded in 2018 and Skip is no longer under active development at Facebook.


I'd like to introduce you to my religion.

https://webassembly.org/


Even carefully designed languages have mistakes.

There's a gazillion engineering hours between JavaScriptCore and V8. It seems crazy to write a JS engine from scratch as opposed to forking JSC or V8.

(For the unawares, RN necessarily uses the system JSC on iOS per Apple requirements, but for Android RN bundles JSC into the APK.)

I don't understand how Hermes will differ from JSC/V8 in terms of functionality and performance. What functionality can be left out of Hermes as compared to JSC/V8 in order to shrink its sie?

What sorts of performance improvements will Hermes have that wouldn't similarly benefit JSC/V8, and why wouldn't Apple/Google include those in their own engines?


Proof is in the pudding: 28% startup speed improvement in MS Office for Android vs V8 with bytecode caching (so AOT compiling the bytecode isn’t a big advantage specific to Hermes):

https://news.ycombinator.com/item?id=20413046

The key is that Hermes is optimized for a totally different environment and workload - RN apps from disk on slow Android devices vs. websites downloaded on desktop computers.

The fact that Hermes is architected for RN from the beginning is key. Bytecode is as compact as possible, and is mmap’d. mmap’d bytecode is a very deep change with huge benefits, but also limits some optimizations other engines rely on, such as inline caching.

Also note Hermes does not have a JIT to save memory and APK size. A lot of the heroic perf work in V8/JSC is in the JIT which is not useful in most RN scenarios/environments.


The same real world react app went from 40MB to 20MB.

They don't ship minified javascript to final app, but bytecode, which they say is 1/3 smaller (both minified). They have moved the parse and compile stages to ahead of time, making the VM smaller, and giving the bytecode benefit. The bytecode benefit also means a quicker time to live/first reponse from 4s to 2s in their example.

Link to the talk, from FB employee announcement made at React Conference today, 15 minutes length. Linked 2 mins in, because the audio is poor to start.

https://youtu.be/zEjqDWqeDdg?t=130


Ah, gotcha. It's moving the parse/compile AOT that I missed. Naively, I'm still surprised they didn't start with JSC/V8 but maybe those engines carry a lot more in them than is needed. Thank you for the link.

This is actually huge and will probably only get better, especially considering now they own their whole JS stack: the framework (React/RN), the language (Flow [1]) and now the VM.

It sounds like Hermes is exclusively for running React Native on mobile. They could start building React directly into Hermes— the reconciling algorithm for example, or maybe even some real parallelism.

Very curious to see how all this keeps evolving.

[1]: https://github.com/facebook/flow


> What functionality can be left out of Hermes as compared to JSC/V8 in order to shrink its sie?

At the moment Hermes isn't compatible with ES6 (it's missing a lot of stuff). Perhaps, since part of the build step for RN anyway is transpiling, they don't need to provide all of ECMA's features. ES5 is more simple, less complex so I wonder if some performance can be had there.

But since they are building an engine strictly for making native apps using JS, there may be shortcuts or other stuff they can drop that JSC/V8 normally have to worry about but that's just speculation.

I'd love to see more info addressing your questions!


V8 and JSC are absolutely amazing pieces of technology. They'll run 60fps WebGL games or console emulators at incredible speeds. Huge props to the engineers that made that happen!

RN apps are rarely CPU bound though, so they don't necessarily benefit as much from those same optimizations.


All those laggy react apps aren't CPU bound? What else is making them laggy?

Poor coding practices, bad state management, and lack of encapsulation between UI components and business logic / data retrieval.

It's really easy to build a React Native app, but not easy to build a really good one.


It's not an unreasonable task for a small team of skilled engineers who know V8 in depth, the kind that FB can and probably has recruited. If they're taking most of what V8 learned over the years into account, they'll know what to prioritize and what to not to.

They also probably know about the tradeoffs. V8 has to choose when interpret and when to compile, when to load things into memory, when to garbage-collect, etc. and they do so keeping in mind it is running javascript from the internet, for any kind of application, on any kind of device.

Hermes can make many more assumptions and so the engineers, even if they built something very similar to V8, can probably dial the knobs much more differently to optimize for what Hermes cares about.


One of the game-breaking things about the older JavaScriptCore engine on Android was that when I debug on Chrome, it has a totally different engine (V8) so, there were code that ran correctly when debugging but crashed on-device.

Will Hermes be able to solve this debugging issue?


Developer here. Yes, it will. JS code you debug through Chrome will still be running on Hermes.

Hermes is using the same debugging protocol as Node. So yes, debugging in Chrome actually runs Hermes code on the device.

Correction: this is not documented yet, but it should already work. Documentation is coming soon.

The current open-source release doesn't have the component that glues the RN inspector with the Hermes debugger to make on-device debugging of Hermes bytecode work. But Hermes does contain a debugger interface, and making this flow this work will happen sometime in the future.

Looks like I was wrong and it’s just the docs that are missing.

I'm moderately curious about why the language of choice was C++ rather than Rust. It seems like all the Ocaml people at Facebook would prefer a more ML-like language.

Here is the full post on Facebook’s Engineering blog: https://code.fb.com/android/hermes/

(I knew nothing about this until 30 minutes ago, but I just did some quick research)

A Quick zero-to-20mph Guide

============================

How it works

------------

1. Results in less to load into memory WHY? It has no Just-in-time (JIT) compilation, instead compiles to bytecode ahead-of-time (AOC). By comparison most (all?) modern browsers have a tricky blend of both.

2. Has no effect on application CPU performance

3. Chrome debugger will connect DIRECTLY to the Hermes engine within the app (simulator or device). By comparison, Chrome debugger uses its own V8 engine to execute code, instead of the JsCoreEngine (?) that React-native uses by default

Results

---------

Mattermost app

1. Time from load until first user interaction: 4.3s -> 2.3s

2. APK size: 41mb -> 22mb

3. Memory: 185Mb -> 136mb


From a similar high elevation perch: https://softwareengineering.stackexchange.com/questions/2746...

Tl;dr AoT can be more resource intensive as a one time cost while JIT uses and limits runtime resources


Worth noting that JSC on iOS for use in app-backend/business-logic code runs in interpreted mode [1].

Are Android versions of RN apps faster because Android's native V8 allows JIT, and Hermes also employs JIT?

[1]: https://stackoverflow.com/questions/45422462/what-does-jit-i...


RN on Android also uses JSC, so no JIT. And, and per the video (https://www.youtube.com/watch?v=zEjqDWqeDdg&feature=youtu.be...) there is no JIT on Hermes either.

JSC on Android can use JIT, but some choose to disable it because it uses more memory than it’s worth.

They harp a lot on how fast it starts up - which sounds great - but I would like to have some solid numbers on what that startup time actually is on actual devices! I can't seem to find anything perusing around the GH page or the site

We have done some internal tests of Hermes on a RN experience within Microsoft Office on Android.

Currently we use V8 with bytecode caching on Android, since it provided better startup performance than the JSC engine that normally ships within RN. So the baseline is likely already faster than stock RN.

V8 runtime Memory Impact: 30MB Hermes runtime memory impact: 21.5MB

V8 time to interaction: 1.4s Hermes time to interaction: 1.1s

We have done similar experiments on a full react-native-windows application, replacing the Chakra JS engine (also already with bytecode so faster than stock RN) with Hermes and had app boot time on a low end device go from 3.8s to 3.1s.


It's a pity the Proxy is not supported mobx is really much nicer approach to state management and usually, apps using mobx are much faster - simply because implementing shouldComponentUpdate properly is hard

You could still use MobX 4 though. It's equally well maintained.

Very nice numbers, although worth mentioning hermes only appears to support es5, so there's way less stuff to load.

Hermes compiles JS ahead of time to bytecode. The VM takes bytecode in as input, not source code. The ES5 vs. ES6 distinction doesn't matter as much as in other engines where the runtime takes source code as input, and as a result has to pay the more expensive ES6 parsing cost at runtime.


Since it's optimized for reducing memory consumption, you'd expect it to make boot time worse?

Impressive numbers. Did you try to use startup snapshot in V8 to improve TTI? https://v8.dev/blog/custom-startup-snapshots

From your numbers:

1. runtime memory reduction: ~25%

2. Boot time reduction: 20%

3. Time to interaction reduction: 20%

For apps with significant boot times, and runtime memory consumption, this is valuable.


For apps with significant boot times, and runtime memory consumption, this is valuable.

This assumes that the reductions are purely proportional to the total and not (at least partially) fixed.


Here are some details on Hermes perf with sample code:

https://mobile.twitter.com/htormey/status/114935339023051980...

Here is a video comparing start times for a Hermes/non Hermes RN app:

https://mobile.twitter.com/nparashuram/status/11493502142154...

I’m currently at Chain React in Portland and they just gave a talk on Hermes. I tweeted a few screenshots that show other perf numbers/technical details for those who are interested.


Thanks for the links!

Will OTA updates with tools like Codepush still be possible with hermes? I'm assuming these tools push the minified js instead of compiled bytecode.

Not clear what version of JS spec it supports.

And what are these "optimizations for running React Native on Android". Just reducing startup/boot time or what?


The VM doesn't run JS directly, just bytecode so the version of the spec supported doesn't matter much. JS can be run through babel before going through the Hermes compiler.

wonderful



Registration is open for Startup School 2019. Classes start July 22nd.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: