Category Archives: Chakra

Auto Added by WPeMatico

Improved JavaScript and WebAssembly performance in EdgeHTML 17 – Microsoft Edge Dev Blog

In every release of Microsoft Edge, we tune the Chakra JavaScript engine to provide better startup and execution performance, with a leaner memory footprint, and with improved responsiveness on real-world workloads.As EdgeHTML 17 rolls out to users as part of the Windows 10 April 2018 Update, we’d like to dive into some of the optimizations we’ve made in the Chakra engine in this release. These ongoing optimizations can have a dramatic impact on the day-to-day browsing experience for end users, resulting in faster sites and web apps.

(Re-)defer parsing for arrow functions and object literals methods
Over the past two Windows releases, we have been improving Chakra’s defer- and re-defer-parsing pipeline, allowing pages to start up faster while consuming less memory.
When given a script, Chakra performs a quick pre-parse check for syntax errors and defers the full parsing of any eligible function until it is first called. Re-deferring happens at a later point when Chakra heuristics determines that a fully parsed function is unlikely to be called again, in which case Chakra releases the memory holding the metadata generated during full parsing and leaves the function effectively in a state as if it had been just pre-parsed and deferred.
In EdgeHTML 17, we have continued to invest in this pipeline, and extended the list of functions eligible to include arrow functions and methods on object literals.

// parsing of these functions are deferred until called
// arrow functions
let addOne = (x) => {x + 1};

// object literal methods
let john = {
name: ‘John Doe’,
get name() {return this.name},
greet() {console.log(‘Hello’)}
};

The impact of this change can vary depending on the sites, but our early experiments show an average memory savings of 7% from this and a few other memory improvements in EdgeHTML 17.
RegExp bytecode refactoring
Many Microsoft Edge users rely on extensions for ad blocking and related scenarios to control their experience while browsing the internet. Some ad blocking extensions are built using a considerable amount of RegExp logic, which motivated us to make a series of bytecode refactoring changes for a leaner experience when running with these extensions enabled in Microsoft Edge.
Most significant among those changes is that Chakra condensed RegExp opcodes from 4 bytes to 1 and packed the structs. While the consequential unalignment might imply a performance slowdown, data collected on various scenarios indicates that it shouldn’t cause any visible performance regression.

As a result of this refactoring, Chakra was able to reduce RegExp bytecode memory in some popular extensions in this release by up to 10%, savings that should be reflected in other apps or sites using RegExp as well.

In addition to memory savings, EdgeHTML 17 brings improvements to several JavaScript built-ins, building on optimizations initially enabled in EdgeHTML 16.
Type sharing for Object.create
Object.create is used to support JavaScript inheritance and null is also often tossed in to create a lean and mean dictionary/property bag. Chakra has an internal type system, and each object in Chakra is represented with an internal dynamic type. Many Chakra optimizations depend on objects with similar layout sharing types with each other. For example, inline caches can store fast paths for various types encountered at call sites, and objects with the same or an equivalent type are able use the same fast path as the cached type.
Type sharing between {x: 1}, {x: 2, y: 2}, {x: 3, z: 3}
Previously, however, objects created by Object.create were associated with a special null type handler in Chakra that cannot share types with other objects, so these optimizations didn’t apply to objects created using Object.create.

let dict1 = Object.create(null);
let dict2 = Object.create(null);
let dict3 = Object.create(null);
dict1.x = 1;
dict2.x = 2; dict2.y = 2;
dict3.x = 3; dict3.z = 3;
// because Object.create cannot share types, o.x in 2nd/3rd calls are cache misses
foo(dict1);
foo(dict2);
foo(dict3);

Beginning with EdgeHTML 17, Object.create returns objects with sharable types. Object.create(Object) now has the normal Object type, and Object.create(null) uses a new null type handler sharable with other Object.create(null) and compatible objects. dict1, 2 and 3 in the above example can now share types and have equivalent types, hence o.x in foo(dict2) and foo(dict3) are cache hits. This change results in an up to 25% speedup in some AngularJS workloads.
Polymorphic inline cache for Object.assign
Object.assign is an ES2015 feature often used to merge or clone objects. In EdgeHTML 16, we improved bracket access (o[prop]) by deploying polymorphic inline cache, which is able to cache multiple types and their associated fast paths at a given call site. With EdgeHTML 17, we’ve propagated the same optimization to benefit Object.assign, which upon de-sugaring involves a sequence of o[prop] style calls.

// an illustrative Object.assign polyfill
function assign(target, …sources) {
sources.forEach(src => {
for (let prop in src) {
// multiple types and fast paths can now be cached at target/src call sites
// therefore improves Object.assign performance
target[prop] = src[prop]
}
});
return target;
}

This simple optimization results in a roughly 2% improvement in some React/Redux workflows, and we expect to further improve performance for this pattern in the next release.
JSON.parse/stringify optimizations
JSON.parse and JSON.stringify are your handy JSON serialization tools in JavaScript. Interestingly, it is also a fairly common pattern to make nested JSON.parse(JSON.stringify(obj)) calls to clone data objects.
Previously, Chakra implemented JSON.stringify by first scaning the object to be serialized, creating the necessary metadata, allocating a large enough buffer for the output string, creating intermediate sub-strings (for each quote, comma, key, value, etc.), and concatenating them together one-by-one.
The creation of intermediate strings caused a lot of redundancy in terms of both time and memory, so in EdgeHTML 17, Chakra skips creating those substrings altogether, and also delays filling up the output string from the metadata until it is actually needed. In the case of a JSON.parse(JSON.stringify(obj) call, the serialized object string is never actually created, and Chakra is able to construct the output object from the metadata generated during stringify.

let obj = {a: 1, b: 2};
let str = JSON.stringify(obj); // scans obj & create metadata
let objClone = JSON.parse(str); // re-construct obj from metadata, no string created
console.log(str); // JSON string creation is delayed until here

This change leads to JSON.stringify being roughly 40% faster in internal performance tests and roughly 70% faster for nested parse/stringify calls.
Rewriting Array Iterators in JavaScript and faster for…of
For…of performance on array also received a major boost in the EdgeHTML 17, and is up to 2.5x faster according to our testing. This speedup is achieved through rewriting the C++ Array Iterators implementation in JavaScript.
We had contemplated a feature rewrite in JS before―many JS optimizations didn’t apply to the C++ implementation, plus next() calls in C++ allocate objects on the heap, which is more expensive than JS stack allocation. The major challenge with a JS implementation is that de-sugared for…of involves a try/catch/finally block to handle cases of abrupt completion, which would have disabled most Chakra optimizations.
To work around those limitations, we made efforts to turn on JIT optimizations for functions with try/catch/finally in EdgeHTML 16, and later enabled inlining for the same as well. With those pre-requisites in place, we were able to rewrite for…of in JS, which runs much faster on non-excepting path.

Microsoft has been working closely with the WebAssembly Community Group (CG) to evolve this growing technology, and we shipped the WebAssembly MVP last year in EdgeHTML 16.
In EdgeHTML 17, WebAssembly (and asm.js) gets even faster with inlining support, which speeds up the workloads we’ve been tracking by about 4.5%. For ChakraCore embedders, WebAssembly is not only available on Windows, but also on Linux and MacOS, as we fixed calling convention issues.
A number of new and exciting WebAssembly features are being discussed within the CG, such as threads, reference types (for host interop), and ES modules integration. We look forward to continuing to collaborate with the CG to move this technology forward and to landing additional features as they progress on the standards track.

It’s always exciting to share more about performance enhancements to Chakra and Microsoft Edge. As always, we’ll continue to make enhancements in future releases, and your feedback is one of the key signals for us to decide what to do next.
We encourage you to dive in and try out these improvements for yourself, 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
Updated June 19, 2018 12:36 pm

Introducing new JavaScript optimizations, WebAssembly, SharedArrayBuffer, and Atomics in EdgeHTML 16

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

Node-ChakraCore update from Node.js Interactive 2017

Earlier this year, we shared an update on some key milestones achieved for Node-ChakraCore like cross-platform support, community participation for N-API, Node-ChakraCore on iOS and more. Today, as Node.js enthusiasts from all over the world gather in Vancouver, Canada for Node.js Interactive, we’d like to share an update on Node-ChakraCore – from its progress in handling production workloads and advancing N-API, to an update on running Node on iOS with ChakraCore.
Node-ChakraCore in production deployments
While Node-ChakraCore is still a pre-release project, and the team has been actively working on improving its reliability, performance and compatibility with popular Node.js modules. As with any new platform, running large production workloads is always a great challenge to test maturity and quality.
Today we are happy to announce that Microsoft Edge Developer portal is handling 100% of its production traffic on Node-ChakraCore! This is a large global website, deployed across multiple datacenters across multiple regions, which handles over 16 million requests per month. Our site uses over 60 npm modules including popular ones like body-parser, cheerio, express, lodash, redis, winston, applicationinsights, and many more.
Node-ChakraCore was a drop-in replacement for Node runtime for this website, demonstrating great compatibility with the existing Node.js module ecosystem—we’re happy to report that not a single line of application code was changed to achieve this migration.
The Microsoft Edge Developer site now runs 100% of production traffic on Node-ChakraCore
Node-ChakraCore is also beginning to see production usage outside of Microsoft properties, specifically for its Time-Travel debugging (TTD) capabilities. Travix is a global online travel company with various travel brands like BudgetAir.com, CheapTickets.nl, vliegwinkel.nl, Vayama.com and FlugLaden. It handles around 3.5 million bookings per year across all its different brands.
Travix uses Node-ChakraCore for their build system for the entire website, including their CI/CD pipeline.
Travix uses Node-ChakraCore for their build system for the entire website, including their CI/CD pipeline. According to Jean Baudin, a software developer at Travix, the main reason for this was Time-Travel debugging capability with Node-ChakraCore.
Using Time-Travel debugging in our CI/CD pipeline has significantly reduced our time to repro and diagnose the issues in our CI/CD pipeline
– Jean Baudin, Software Developer, Travix.com
Their home-grown CI/CD pipeline uses TTD record functionality for pre-production testing to automatically capture traces in case of errors, which is then used offline by developers to quickly reproduce the problem in VSCode with ability to step back and understand the control flow of the faulty execution, thereby saving time in searching through logs and reconstruction of the repro steps.  Travix also uses Node-ChakraCore in its production deployment of one of their microservices that handles its gateway to connect to KongDB for their database access.
These deployments are a significant milestone in our journey to enable Node-ChakraCore as a drop-in replacement for production sites in the future. Our goal is to exit pre-release status having rigorously validated Node-ChakraCore to meet the high quality bar expected by Node.js developers.
ABI Stable Node.js API (N-API)
Evolving the Node.js ecosystem through community participation is one of the main objectives of Node-ChakraCore and we are humbled to have the opportunity to participate in the conversations regarding future of Node.js. The N-API project is one such example of the Node-ChakraCore team collaborating with the API working group and others in the community to solve a real-world problem for Node.js native module developers by helping define and implement a new ABI stable API surface for Node.js. ABI stability is very important to have a healthy and robust module ecosystem that allows more potential for future growth of the platform. N-API helps reduce the maintenance costs for native module authors by allowing them to compile their modules just once for all future Node versions. More significantly for native module consumers, it reduces friction in upgrading to new Node version since the native module dependencies will “just work” against the new version of Node.
N-API has been available as an experimental feature since May 2017 in Node 8.0, and we’ve been excited by the interest shown in just a few short months, as can be seen by the chart below showing downloads of the node-addon-api module.
Downloads of the node-addon-api module (via npm-stat.com)
We’ve heard lots of great feedback from the community on the initial implementation. The working group has been able to quickly act on your feedback, and has recently landed several important changes available in Node.js 8.6—most notably, the removal of the command line flag, which now enables N-API module deployments in prod/pre-prod environment without having to change the deployment scripts, making it easier to interop with ES6 modules and support for async_hooks. With this, all known breaking changes have landed in Node 8.6, and we now strongly encourage module maintainers to consider porting a native module to N-API.
The next milestone for N-API is to exit the experimental status, which depends on community adoption. Check out the N-API github repository to find out different ways to help in moving this project forward.
Node.js for Mobile Apps
Node.js was born in the cloud, but recently we’ve seen growing interest in running Node.js on mobile devices. Some examples include hood.ie’s offline first initiative, Rockwell Automation’s TeamOne solution for factory floor device automation, and Luna from Craftwork, which runs both on a set-top box and on an iPad to allow same content consumption experience on a TV and on a tablet, and many more.
Janea Systems’ recent announcement about their Node.js for Mobile Apps project is another step towards addressing this growing trend. Earlier this year Janea Systems had shown a demo of Node.js running on iOS, today the project is available for free and is open source so that the community can start building on it.  We are delighted to see Node-ChakraCore being used as a key part of this solution to provide Node.js runtime on iOS and to expand the reach of Node.js usage.
What’s Next
The focus for Node-ChakraCore is to continue making progress on performance, compatibility and cross-platform support for the EcmaScript Internationalization API. In the last 3 months, Node-ChakraCore has gained 30% perf improvement on ACME Air benchmark on Linux. We will be sharing more on this in the coming months.
Get involved
We would like to thank everyone who is already involved and invite more people to help advance the Node-ChakraCore project. If you are building something using Node-ChakraCore, we’d love to hear from you and learn from your experience. Here are some of the ways to help out. If you are a:
Node.js Developer – Try testing Node-ChakraCore in your project, and use Time-Travel debugging with VSCode and let us know how it goes.
Node.js module maintainer – Try testing your module with Node-ChakraCore. Use these instructions to add Node-ChakraCore in your own CI to ensure ongoing compatibility. If you run into issues, please let us know at our repo or our gitter channel.
Node.js native module maintainer – Consider porting your module to N-API. N-API is the future of native modules on Node, and porting your module will help you reduce your maintenance costs and be ready for future versions of Node.js and will also work with Node-ChakraCore.
As always, we are eager to hear your feedback, so please keep it coming. Find us on Twitter @ChakraCore, our gitter channel or open an issue on Node-ChakraCore github repo to start a conversation.
― Arunesh Chandra, Sr. PM JavaScript Platform and Tools