WhoBuilt

Hermes: better performance with runtime bytecode translation

Oct 4, 2024· 24 min· 1.9K views·Watch on YouTube

Speaker

Tzvetan Mikov, a member of Meta’s Hermes team, presents new work on Hermes performance at RUC 2024, hosted by Callstack.

Hermes moves work to build time

Mikov contrasts web engines, which parse, compile, and optimize at runtime, with Hermes, which compiles ahead of time to bytecode. Hermes loads that bytecode lazily, keeping startup work and memory use low. Its startup time does not depend on the size of the input bundle.

Static Hermes adds type information

Static Hermes uses type annotations to compile typed bytecode or native machine code. Mikov says it can approach C++ performance without relying on repeated runtime guesses about types. Adoption is complicated because build pipelines often erase annotations, native compilation makes over-the-air updates harder, and untyped JavaScript still needs to run well.

Bytecode translation speeds up runtime execution

Hermes translates bytecode instructions into machine instructions on the device, reducing the interpreter’s instruction decoding and dispatch work. Apps can still ship bytecode and use over-the-air updates. Mikov calls the approach bytecode translation; technically it is a JIT, but it avoids speculative optimization by building on Hermes’s ahead-of-time compiler.

Benchmarks show gains, especially for typed code

On several Octane benchmarks, untyped code runs about 50% faster with translation. In typed benchmarks, the Ray Tracer runs nine times faster with typed bytecode and translation than with original Hermes, while native code is faster still by a smaller margin. Mikov also shows an untyped Mandelbrot renderer that ran faster than he expected.

Fast paths and rollout plans

Mikov explains that replacing bytecode instructions with function calls gave almost no improvement. Performance improved when common cases, such as numeric multiplication, got a fast path and unusual cases branched to slower handling. He expects bytecode translation to arrive before default support for static types, which depends on preserving annotations through build pipelines.

Takeaways

  • Moving parsing and compilation off the device can reduce startup work and memory use.
  • A lightweight bytecode translator can improve untyped performance while preserving bytecode delivery and over-the-air updates.
  • Type information can unlock larger gains, but only if build pipelines preserve annotations.
  • For runtime optimization, fast paths for common operations can matter more than routing every instruction through a function call.
  • Plan performance improvements for untyped code too, since typed code may cover only part of an application.

Mentioned in this talk

Search inside this talk

What was claimed 12

Show all 12 facts

Related talks