<commit_before>---
title: 'Sparkplug — a non-optimizing JavaScript compiler'
author: '[<NAME>](https://twitter.com/leszekswirski) — maybe not the brightest spark, but at least the fastest one'
avatars:
  - leszek-swirski
date: 2021-05-27
tags:
  - JavaScript
extra_links:
  - href: https://fonts.googleapis.com/css?family=Gloria+Hallelujah&display=swap
    rel: stylesheet
description: 'In V8 v9.1 we’re improving V8 performance by 5–15% with Sparkplug: a new, non-optimizing JavaScript compiler.'
tweet: '1397945205198835719'
---

<!-- markdownlint-capture -->
<!-- markdownlint-disable no-inline-html -->
<style>
  svg {
    --other-frame-bg: rgb(200, 200, 200, 0.2);
    --machine-frame-bg: rgb(200, 200, 200, 0.5);
    --js-frame-bg: rgba(212, 205, 100, 0.603);
    --interpreter-frame-bg: rgba(215, 137, 218, 0.5);
    --sparkplug-frame-bg: rgba(235, 163, 104, 0.5);
  }
  svg text {
    font-family: Gloria Hallelujah, cursive;
  }
  .flipped .frame {
    transform: scale(1, -1);
  }
  .flipped .frame text {
    transform:scale(1, -1);
  }
</style>
<!-- markdownlint-restore -->

Writing a high-performance JavaScript engine takes more than just having a highly optimising compiler like TurboFan. Particularly for short-lived sessions, like loading websites or command line tools, there’s a lot of work that happens before the optimising compiler even has a chance to start optimising, let alone having time to generate the optimised code.

This is the reason why, since 2016, we’ve moved away from tracking synthetic benchmarks (like Octane) to measuring [real-world performance](/blog/real-world-performance), and why since then we’ve worked hard on the performance of JavaScript outside of the optimising compiler. This has meant work on the parser, on streaming, on our object model, on concurrency in the garbage collector, on caching compiled code… let’s just say we were never bored.

As we turn to improving the performance of the actual initial JavaScript execution, however, we start to hit limitations when optimising our interpreter. V8’s interpreter is highly optimised and very fast, but interpreters have inherent overheads that we can’t get rid of; things like bytecode decoding overheads or dispatch overheads that are an intrinsic part of an interpreter’s functionality.

With our current two-compiler model, we can’t tier up to optimised code much faster; we can (and are) working on making the optimisation faster, but at some point you can only get faster by removing optimisation passes, which reduces peak performance. Even worse, we can’t really start optimising earlier, because we won’t have stable object shape feedback yet.

Enter Sparkplug: our new non-optimising JavaScript compiler we’re releasing with V8 v9.1, which nestles between the Ignition interpreter and the TurboFan optimising compiler.

![The new compiler pipeline](/_svg/sparkplug/pipeline.svg)

## A fast compiler

Sparkplug is designed to compile fast. Very fast. So fast, that we can pretty much compile whenever we want, allowing us to tier up to Sparkplug code much more aggressively than we can to TurboFan code.
<commit_msg>Use consistent color notation<commit_after>---
title: 'Sparkplug — a non-optimizing JavaScript compiler'
author: '[<NAME>](https://twitter.com/leszekswirski) — maybe not the brightest spark, but at least the fastest one'
avatars:
  - leszek-swirski
date: 2021-05-27
tags:
  - JavaScript
extra_links:
  - href: https://fonts.googleapis.com/css?family=Gloria+Hallelujah&display=swap
    rel: stylesheet
description: 'In V8 v9.1 we’re improving V8 performance by 5–15% with Sparkplug: a new, non-optimizing JavaScript compiler.'
tweet: '1397945205198835719'
---

<!-- markdownlint-capture -->
<!-- markdownlint-disable no-inline-html -->
<style>
  svg {
    --other-frame-bg: rgb(200 200 200 / 20%);
    --machine-frame-bg: rgb(200 200 200 / 50%);
    --js-frame-bg: rgb(212 205 100 / 60%);
    --interpreter-frame-bg: rgb(215 137 218 / 50%);
    --sparkplug-frame-bg: rgb(235 163 104 / 50%);
  }
  svg text {
    font-family: Gloria Hallelujah, cursive;
  }
  .flipped .frame {
    transform: scale(1, -1);
  }
  .flipped .frame text {
    transform:scale(1, -1);
  }
</style>
<!-- markdownlint-restore -->

Writing a high-performance JavaScript engine takes more than just having a highly optimising compiler like TurboFan. Particularly for short-lived sessions, like loading websites or command line tools, there’s a lot of work that happens before the optimising compiler even has a chance to start optimising, let alone having time to generate the optimised code.

This is the reason why, since 2016, we’ve moved away from tracking synthetic benchmarks (like Octane) to measuring [real-world performance](/blog/real-world-performance), and why since then we’ve worked hard on the performance of JavaScript outside of the optimising compiler. This has meant work on the parser, on streaming, on our object model, on concurrency in the garbage collector, on caching compiled code… let’s just say we were never bored.

As we turn to improving the performance of the actual initial JavaScript execution, however, we start to hit limitations when optimising our interpreter. V8’s interpreter is highly optimised and very fast, but interpreters have inherent overheads that we can’t get rid of; things like bytecode decoding overheads or dispatch overheads that are an intrinsic part of an interpreter’s functionality.

With our current two-compiler model, we can’t tier up to optimised code much faster; we can (and are) working on making the optimisation faster, but at some point you can only get faster by removing optimisation passes, which reduces peak performance. Even worse, we can’t really start optimising earlier, because we won’t have stable object shape feedback yet.

Enter Sparkplug: our new non-optimising JavaScript compiler we’re releasing with V8 v9.1, which nestles between the Ignition interpreter and the TurboFan optimising compiler.

![The new compiler pipeline](/_svg/sparkplug/pipeline.svg)

## A fast compiler

Sparkplug is designed to compile fast. Very fast. So fast, that we can pretty much compile whenever we want, allowing us to tier up to Sparkplug code much more aggressively than we can to TurboFan code.

{'fraction_non_alphanumeric': 0.08229665071770335, 'fraction_numerical': 0.03253588516746411, 'mean_word_length': 4.265323257766583, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, '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': '6776216', 'n_tokens_mistral': 1919, 'n_tokens_neox': 1695, 'n_words': 811}