Hermes Analysis
I have been digging a little bit into Hermes (a mobile first JS engine) focused on React Native. Since I shared most of it on twitter, I want to "copy" the content here to persist it for me, I know I am coming back to this eventually and this way I get up to speed faster.
Object vs. Map
I think I have an idea of how a bytecode based VM works, so I was curious to dig a little deeper. And I am going to use an example that I remember @Benedikt told me about once, where a v8 is struggling with. It is the usage of the very overloaded and powerful object literal in JavaScript, while one actually is "just" doing the work that a JavaScript Map is way more ideal for.
Besides the speed gain a VM might give you when using a Map, I also like the explicitness in code. A piece of code that reads map.has('key')
is way more explicit than any way you can write this with an object. And you also know it does ONLY that.
So I thought I would like to see what kinda code hermes produces when I use an object literal vs. a Map. Find my annotated tweets below.
I am digging into @HermesEngineβs bytecode.
β @wolframkriesing March 14, 2021
Letβs see how object vs. Map.
// v1
const o = {one: 1, two: 2};
print(o.one);
// v2
const m = new Map([['one', 1], ['two', 2]]);
print(m.get('one'));
1/
Why?
β @wolframkriesing March 14, 2021
I once learned that object is so overloaded and complex (in v8) that for a simple map, using Map is way more efficient. Besides that the code is also way more explicit.
2/
The resulting bytecode looks like this. I believe the images are the relevant parts of the bytecode.
β @wolframkriesing March 14, 2021
Itβs easy to see which code is shorter. Not sure (yet) if relevant. Shorter bytecode is good for the bundle size, but now I need to look under the hood.
3/
I have generated and screenshotted the images in the hermes playground.
Reading the #hermes VM interpreter code [1] I canβt but wonder why vm authors seem to like big code files instead of many smaller modular ones.
β @wolframkriesing March 14, 2021
[1] https://github.com/facebook/hermes/blob/master/lib/VM/Interpreter.cpp
With uxebu we used to build a flash parser and a VM for ActionScript 3 bytecode, so I think I have seen some alike stuff being developed and I can't get rid of the feeling that there is a certian type of programmer, that likes to write this code :).
Besides the style of code, it seems that I need to dive even deeper. Just looking at the bytecode is not very conclusive and reveals a different picture to what I expected. The bytecode for the Map-version is longer. So I guess the VM code under the hood might reveal some more insights.
v1
β @wolframkriesing March 14, 2021
createObjectFromBuffer 120 LOC
v2
`CreateThis` sounds complex, it calls `Callable::newObject` which looks like it wants quite some memory.
To create the map an array is used, `Interpreter::createArrayFromBuffer` is just 25 LOC, Sounds efficient compared to an object.
/5
I definitely canβt draw any conclusion about object vs. Map in regards to resource usage. But I read some hermes VM code and believe I have a feeling for what is going on under the hood. I am far from understanding it, but it looks like there are people who love that stuff ;)
β @wolframkriesing March 14, 2021
6/
In regards to bytecode size, bundle size, mobile app size in the end, objects (as used here) seems to result in a smaller bytecode size.
β @wolframkriesing March 14, 2021
At runtime, I didnβt measure any numbers, so I canβt say.
7/
In the talk where Marc introduced #hermes he said it has no JIT. Looking at the parameters [1], it looks like this has changed, or I don't understand things really.
β @wolframkriesing March 14, 2021
Anyways, this is me sharing my half-baked knowledge about hermes.
[1] https://hermesengine.dev/playground/ (click the ?)
8/8
Besides all the analysis and the time spent, I can't say I understand all of it. But I get some feeling for hermes. I am wondering if there are more optimziation possible. Especially given, that hermes dismisses some JS features already. There might be more possible to get to a smaller but still very usable JS engine, that might has some good tradeoffs for an even bigger resource consumption gain.
I keep look out.