Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code Caching for JS developers

Leszek Swirski
September 20, 2018

Code Caching for JS developers

Video: https://skillsmatter.com/skillscasts/12178-code-caching-for-js-developers

Everybody knows that the fastest way to do something is to not do it at all, and V8 is no exception. After all, why parse and compile JavaScript that we’ve already parsed and compiled before?

But the caching behaviour of a JavaScript engine can be a bit of a mystery. What even gets cached, and why? Who decides when it is cached and where is it stored — and how many caches even are there? What if I use a service worker?

This talk will demystify code caching in V8, describing how code caching interacts with the disk, how in-memory code is re-used, how compiled scripts are serialized, and most importantly, how JS developers can benefit from these optimizations.

Leszek Swirski

September 20, 2018
Tweet

Other Decks in Technology

Transcript

  1. 0011010 0100110 1100101 Parse/Compile source code Execute script V8 Isolate

    Cache Isolate cache source code <script src="script.js"> Cold run ❄
  2. 0011010 0100110 1100101 Parse/Compile source code Execute script V8 Isolate

    Cache Isolate cache source code Cold run ❄ <script src="script.js">
  3. 0011010 0100110 1100101 Parse/Compile source code V8 Isolate Cache Isolate

    cache source code <script src="script.js"> Warm run ☀
  4. 0011010 0100110 1100101 Parse/Compile source code V8 Isolate Cache Isolate

    cache source code <script src="script.js"> Warm run ☀
  5. 0011010 0100110 1100101 source code script V8 Isolate Cache Isolate

    cache source code Lookup <script src="script.js"> Warm run ☀
  6. 0011010 0100110 1100101 Parse/Compile source code script <script src="script.js"> V8

    Isolate Cache Isolate cache source code Execute Warm run ☀
  7. 0011010 0100110 1100101 source code script <script src="script.js"> V8 Isolate

    Cache Isolate cache source code Execute Cache hit rate: 80% Lookup Warm run ☀
  8. V8 Isolate Cache Isolate cache source code source code 0011010

    0100110 1100101 Isolate cache source code source code <script src="script.js"> <script src="script.js">
  9. V8 Isolate Cache Isolate cache source code source code 0011010

    0100110 1100101 Isolate cache source code source code script <script src="script.js"> <script src="script.js"> Lookup
  10. V8 Isolate Cache Isolate cache source code Parse/Compile source code

    0011010 0100110 1100101 Isolate cache source code source code script script <script src="script.js"> <script src="script.js"> Lookup
  11. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> Cold run ❄
  12. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> script.js [data] Cold run ❄
  13. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> script.js [data] Timestamp Cold run ❄
  14. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> script.js [data] Timestamp Warm run ☀
  15. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> script.js [data] Timestamp Warm run ☀
  16. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> script.js [data] Timestamp Warm run ☀ ≥72 hours
  17. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> script.js [data] Timestamp Warm run ☀ ≥72 hours
  18. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response <script src="script.js"> Warm run ☀ script.js [data] <72 hours Timestamp
  19. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response Serialize <script src="script.js"> Warm run ☀ script.js [data] <72 hours Timestamp
  20. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response Serialize <script src="script.js"> Warm run ☀ script.js [data] <72 hours Timestamp
  21. Parse/Compile source code Execute Chrome Resource Cache Resource cache URL

    Metadata Response Serialize <script src="script.js"> Warm run ☀ script.js [data] <72 hours Code cache
  22. Chrome Resource Cache Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache
  23. Chrome Resource Cache Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache
  24. code cache Chrome Resource Cache Resource cache URL Metadata Response

    Deserialize Hot run <script src="script.js"> script.js [data] Code cache
  25. code cache Chrome Resource Cache Resource cache URL Metadata Response

    Deserialize Hot run <script src="script.js"> script.js [data] Code cache
  26. code cache Execute Chrome Resource Cache Resource cache URL Metadata

    Response Deserialize Hot run <script src="script.js"> script.js [data] Code cache
  27. code cache Execute Deserialize <script src="script.js"> Chrome Resource Cache Hot

    run Resource cache URL Metadata Response script.js [data] Code cache Cache hit rate: 80%*
  28. code cache Execute Deserialize <script src="script.js"> Chrome Resource Cache Resource

    cache URL Metadata Response Hot run script.js [data] Code cache Cache hit rate: 80%* * of cacheable external scripts
  29. Code cache Cache Chrome Resource Cache Network cache URL Response

    Hot run <script src="script.js"> script.js [data] URL script.js Code cache
  30. Code cache Cache Chrome Resource Cache Network cache URL Response

    Hot run <script src="script.js"> script.js [data] URL script.js Code cache
  31. Code cache Cache Chrome Resource Cache Network cache URL Response

    Hot run <script src="script.js"> script.js [data] URL script.js Code cache
  32. Code caching Cold run ❄ Warm run ☀ Hot runs

    Use isolate cache Compile Compile + Serialize Deserialize In-memory (same tab*) On-disk * actually “same V8 isolate”, which means same renderer process and same thread
  33. Code caching? Cold run ❄ Warm run ☀ Hot runs

    Use isolate cache Compile + Serialize? Deserialize? In-memory (same tab*) On-disk * actually “same V8 isolate”, which means same renderer process and same thread
  34. don’t change code Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache
  35. don’t change code Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache HTTP GET script.js
  36. don’t change code Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache HTTP 304 Not Modified
  37. don’t change code Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache HTTP GET script.js
  38. don’t change code Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache HTTP 200 [data2]
  39. don’t change code Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data2] Code cache HTTP 200 [data2]
  40. don’t change URLs Resource cache URL Metadata Response Hot run

    <script src="script.js"> script.js [data] Code cache
  41. don’t change URLs Resource cache URL Metadata Response Hot run

    <script src="script.js?my_cool_param=1"> script.js [data] Code cache
  42. don’t change URLs Resource cache URL Metadata Response Hot run

    <script src="script.js?my_cool_param=1"> script.js [data] Code cache Cold run ❄ script.js?… [data]
  43. Parse/Compile source code Execute don’t change behaviour Resource cache URL

    Metadata Response Serialize <script src="script.js"> Warm run ☀ script.js [data] Timestamp
  44. Serialize? Execute? Parse/Compile source code don’t change behaviour Resource cache

    URL Metadata Response <script src="script.js"> Warm run ☀ script.js [data] Timestamp
  45. Parse/Compile source code don’t change behaviour Resource cache URL Metadata

    Response <script src="script.js"> Warm run ☀ script.js [data] Timestamp top-level script skipped inner functions Execute Serialize
  46. Parse/Compile source code don’t change behaviour Resource cache URL Metadata

    Response <script src="script.js"> Warm run ☀ script.js [data] Timestamp top-level script skipped Execute parsing inner functions
  47. Parse/Compile source code don’t change behaviour Resource cache URL Metadata

    Response <script src="script.js"> Warm run ☀ script.js [data] Timestamp top-level script skipped Execute Serialize parsing inner functions
  48. Parse/Compile source code don’t change behaviour Resource cache URL Metadata

    Response <script src="script.js"> Warm run ☀ script.js [data] Timestamp top-level script skipped Serialize Execute parsing inner functions
  49. code cache Execute Resource cache URL Metadata Response Deserialize Hot

    run <script src="script.js"> script.js [data] Code cache don’t change behaviour parsing inner functions
  50. function foo() { // Lotsa code } function bar() {

    // Lotsa code } if (Math.random() > 0.5) { foo() } else { bar() }
  51. function foo() { // Lotsa code } function bar() {

    // Lotsa code } if (random() > 0.5) { foo() } else { bar() } 10 WAYS TO INCREASE CODE CACHING NUMBER 4 WILL SHOCK YOU!
  52. <!-- page1.html --> <script> function foo() { // Lotsa code

    } foo() </script> <!-- page2.html --> <script> function foo() { // Lotsa code } foo() </script>
  53. <!-- page1.html --> <script src="foo.js"></script> <script> foo() </script> // foo.js

    function foo() { // Lotsa code } <!-- page2.html --> <script src="foo.js"></script> <script> foo() </script>
  54. <!-- page1.html --> <script src="page1.js"></script> <!-- page2.html --> <script src="page2.js"></script>

    // page1.js (function() { // lodash ... root._ = lodash() }).call(this) (function page1code(){ // ... })() // page2.js (function() { // lodash ... root._ = lodash() }).call(this) (function page2code(){ // ... })()
  55. <!-- page1.html --> <script src="lib.js"></script> <script src="page1.js"></script> <!-- page2.html -->

    <script src="lib.js"></script> <script src="page2.js"></script> // page1.js (function page1code(){ // ... })() // page2.js (function page2code(){ // ... })() // lib.js (function() { // lodash ... root._ = lodash() }).call(this)
  56. Resource cache [data] [data] Response Metadata URL page1.js Code cache

    page2.js Code cache lib.js [data] Code cache
  57. <!-- index.html --> <script src="main.js"></script> // main.js (function() { //

    lodash ... root._ = lodash() }).call(this) (function main(){ // ... })()
  58. <!-- index.html --> <script src="lib.js"></script> <script src="main.js"></script> // main.js (function

    main(){ // ... })() // lib.js (function() { // lodash ... root._ = lodash() }).call(this)
  59. // foo.js (function foo(){ // 800b })() // bar.js (function

    bar(){ // 800b })() < 1Kb < 1Kb Dear reader, originally this slide said 1Mb. What I meant was a much more reasonable 1Kb
  60. // foobar.js (function foo(){ // 800b })() (function bar(){ //

    800b })() >1Kb Dear reader, originally this slide said 1Mb. What I meant was a much more reasonable 1Kb
  61. Something. avoid inline scripts split out libraries from code group

    small files together use service worker caches
  62. // main.js navigator.serviceWorker.register('/sw.js') // sw.js self.addEventListener('fetch', event=>{ async function cachedFetch(event)

    { const cache = await caches.open(cacheName) let response = await cache.match(event.request) if (response) return response response = await fetch(event.request) cache.put(event.request, response.clone()) return response } event.respondWith(cachedFetch(event)) }) self.addEventListener('install', event=>{ async function buildCache() { const cache = await caches.open(cacheName) return cache.addAll([ '/main.css', '/main.js', '/offline.html' ]) } event.waitUntil(buildCache()) })
  63. Parse/Compile source code Service Worker cache Resource cache URL Metadata

    Response <script src="script.js"> Warm run ☀ script.js [data] Timestamp top-level script skipped Execute Serialize
  64. Parse/Compile source code Service Worker cache Service worker cache URL

    Metadata Response <script src="script.js"> Warm run ☀ script.js [data] Timestamp top-level script Execute Serialize skipped
  65. Parse/Compile source code Service Worker cache Service worker cache URL

    Metadata Response <script src="script.js"> script.js [data] top-level script Execute Serialize skipped Cold run ❄
  66. Parse/Compile source code Service Worker cache Service worker cache URL

    Metadata Response <script src="script.js"> script.js [data] top-level script Execute Serialize compiled Cold run ❄
  67. Something. avoid inline scripts split out libraries from code group

    small files together use service worker caches Nothing. don’t change code don’t change URLs don’t change behaviour What should JS developers do?
  68. Tracing is tricky trace in a new profile google-chrome --user-data-dir=$(mktemp

    -d) don’t have other tabs open don’t install extensions
  69. 2018-07-04, Version 10.6.0 Notable changes: * build: * Node.js should

    now be about 60% faster to startup than the previous version, thanks to the use V8's code cache feature for core modules.
  70. const vm = require('vm') const script = new vm.Script(code, {

    cachedData: cachedDataBuffer }) script.runInThisContext()
  71. const vm = require('vm') const script = new vm.Script(code, {

    cachedData: cachedDataBuffer }) script.runInThisContext() const cachedDataBuffer = script.createCachedData()
  72. Code caching for JS Developers Leszek Swirski Cold run ❄

    Warm run ☀ Hot runs Use isolate cache Compile Compile + Serialize Deserialize In-memory On-disk Nothing. don’t change code don’t change URLs don’t change behaviour Something. avoid inline scripts split out libraries from code group small files together use service worker caches Profile. chrome://tracing What should JS developers do?