JavaScript performance has always been a core area of focus for our team. Every release, we look for opportunities to improve end users’ browsing experience on real workloads with shorter start-up time, faster execution, and leaner memory usage. These efforts are guided by invaluable ongoing customer feedback and telemetry data.
In this blog post, we will share a few new performance enhancements in the Chakra JavaScript engine, as well as updates on the availability of on-by-default WebAssembly, SharedArrayBuffer and Atomics support in Chakra and Microsoft Edge in EdgeHTML 16 with the Windows 10 Fall Creators Update.
More memory savings from deferring/re-deferring functions
In EdgeHTML 15, Chakra introduced the capability to re-defer functions. To briefly recap Chakra’s deferral/re-deferral pipeline, at start-up time Chakra performs a quick pre-parsing pass to check for syntax errors, and then defers the full parsing of eligible functions until they are first executed. At a later point, if heuristics determine that a fully-parsed function will most likely never be executed again, Chakra dumps its metadata generated since full-parsing and returns to a lean state as if the function is just pre-parsed and being deferred (hence the name re-deferral).
The deferral/re-deferral feature helps sites boost start-up time and save memory on redundant functions (imagine pulling a bunch of libraries and only just using 30% of the code, sound familiar?).
In EdgeHTML 16, we’ve addressed the feature’s previous limitation on handling functions in lexical and parameter scopes, and allowed functions in all scopes to be deferred and re-deferred. For example, it is common to have large chunks of scripts wrapped in giant try blocks for error handling, and functions enclosed in a block are now eligible for deferral/re-deferral.
// foo can be deferred/re-deferred after the Fall Creators Update // example 1 - lexical/block scope try { function foo() {...} var bar = foo(); } // example 2 - parameter scope function bar(foo = function(){...})) {...}
This change further improves memory savings made possible by deferral/re-deferral. The exact effect varies depending on the coding patterns of the sites. According to our experiment on a small sample of popular sites, this change along with others in the past update typically reduce the memory allocated by Chakra by 4-9%. The impact can also be much larger in some cases―such as a ~35% memory saving on Gmail.
Polymorphic inline cache for property access using square brackets (object[‘property’])
Polymorphic inline cache (PIC) is an optimization technique employed in Chakra (and many other runtimes) since Chakra’s inception. Chakra has an internal type system that maps each value to its type. When the Chakra Just-In-Time compiler (JIT) generates optimized code for hot code paths, Chakra may deploy an inline cache at each call site (location for function/subroutine calls such as property access) to memorize and store fast paths for the types encountered.
Polymorphic inline cache is a kind of inline cache that can remember multiple types at a given call site. In EdgeHTML 16, Chakra added the ability to place polymorphic inline cache for the object[‘property’] syntax, allowing cases where object may be of different types to be optimized.
// example - obj can be of {a: Number} or String type let arr = [{a: Math.random()}, Math.random().toString()]; arr.forEach(obj => { for (propNames in obj) { if (obj.hasOwnProperty(propNames)) { // without PIC, multiple types lead to generic slow path // with PIC, both types for obj console.log(obj[propNames]); } } });
This change should benefit typical users browsing sites using bracket notation and shows up as up to 8% speedup on tests utilizing Angular and React frameworks.
Enable optimizations for functions with try/finally
In JavaScript, it is a best practice to use the finally clause to gracefully clean up resources following a try block. Until the latest update, Chakra did not optimize functions that include a try/finally block because it was a non-trivial job to account for exceptions and unwinding in JIT optimizations.
Starting with EdgeHTML 16, when the Chakra JIT analyzes functions and builds the flow graph, it separates the excepting and non-excepting cases and creates two paths for a try/finally block, allowing general optimizations to be applied on the non-excepting path and forcing a bailout in case of an exception.
More optimizations for try/catch/finally are just on the horizon. ChakraCore recently added support for inlining in functions with try/catch/finally and you can expect this change to propagate to Chakra and Microsoft Edge in the next major Windows update.
WebAssembly, SharedArrayBuffer, and Atomics on by default
In the previous update, Chakra and Microsoft Edge debuted WebAssembly Minimum Viable Product (MVP), SharedArrayBuffer and Atomics support behind the “Experimental JavaScript Features” flag. With a bit of tuning in the past few months, these features are now stable and enabled by default in EdgeHTML 16.
Several changes also help improve WebAssembly performance in Chakra by 20-25% on workloads we have been tracking. Try it out for yourself! Point Microsoft Edge at a fun WebAssembly game like Funky Karts to see the improvement with no flags required!
Demo of Funky Karts in WebAssembly in Microsoft Edge (demo by Ross Smith)
Microsoft has been and will continue to work closely with Mozilla, Google, Apple and others in the WebAssembly community to move the technology forward. Impactful post-MVP features such as threads and GC are currently being explored in the WebAssembly Community Group.
Get involved
We are excited to share these new performance optimizations as well as on-by-default WebAssembly, SharedArrayBuffer, and Atomics support in Chakra and Microsoft Edge.
As always, we’re making more enhancements in future releases, and your feedback is one of our key signals for what to do next. So stay tuned and be sure to share your thoughts with us on the ChakraCore repo, or via @MSEdgeDev and @ChakraCore on Twitter!
― Limin Zhu, Program Manager, Chakra
The post Introducing new JavaScript optimizations, WebAssembly, SharedArrayBuffer, and Atomics in EdgeHTML 16 appeared first on Microsoft Edge Dev Blog.