Bug 212962 - 4x slow execution slowdown when comparing the same codebase targeting ES2015 vs. ES5
Summary: 4x slow execution slowdown when comparing the same codebase targeting ES2015 ...
Status: RESOLVED DUPLICATE of bug 199866
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: Mac macOS 10.15
: P2 Normal
Assignee: Nobody
Keywords: InRadar
Depends on:
Reported: 2020-06-09 00:02 PDT by Mihai Parparita
Modified: 2020-10-20 23:25 PDT (History)
7 users (show)

See Also:

ES2015 Time Profile Instruments output (1.09 MB, application/zip)
2020-06-09 00:02 PDT, Mihai Parparita
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mihai Parparita 2020-06-09 00:02:28 PDT
Created attachment 401421 [details]
ES2015 Time Profile Instruments output

We have have recently begun evaluating directly shipping ES2015 code in our application, instead of down-compiling it down to ES5. We have observed a significant performance regression when doing this in Safari.

Here is a somewhat reduced test case, that displays the execution time of the critical part our application (the time to load/render a document):
ES5 version: http://persistent.info/webkit/test-cases/es2015-slowness/?es5 - takes around 80ms
ES2015 version: http://persistent.info/webkit/test-cases/es2015-slowness/?es2015 - takes around 312ms

This has been observed in both Safari 13.1.1 and Safari Technology Preview 107 on macOS 10.15.5

A timeline recording shows significant time spent in the root "(program)" part of the script, which does not shed much light. 

We thus also ran the Web Content process under Instruments, and compared the top functions for the ES5 and ES2015 versions. The latter seemed to spend a lot of time in JSC::BytecodeGenerator::getVariablesUnderTDZ() and creating/populating hash tables that back  JSC::CompactVariableEnvironment (see attached es2015.trace file).

Given this clue, we generated a variant of the ES2015 output where all `let`s and `const`s were replaced with `var`s, and that yielded better results, though still not as fast as the ES5 version:

http://persistent.info/webkit/test-cases/es2015-slowness/?es2015-var - takes around 155ms

In case it helps, the original code is in TypeScript (using ES207 features including async/await). The TypeScript compiler handles the down-leveling to ES2015 or ES5. Rollup is then used as a bundler, it generates the IIFE that the entire script is wrapped in. I'm happy to try to generate an even smaller benchmark if it proves helpful.
Comment 1 Mihai Parparita 2020-06-09 00:16:56 PDT
I have observed the same time difference in the current WebKit nightly build (r262775)
Comment 2 Mihai Parparita 2020-06-09 10:39:13 PDT
As a further experiment, I generated a variant of the ES2015 output that did not wrap the output in an IIFE, and that had comparable performance to the ES5 output that did:

http://persistent.info/webkit/test-cases/es2015-slowness/?es2015-no-iife - takes around 91ms

However, that pollutes the global namespace (and exposes symbols that we would prefer not to be accessible). If we take the script and load it with <script type="module">, then we're back to where we started from:

http://persistent.info/webkit/test-cases/es2015-slowness/?es2015-no-iife-module - takes around 330ms

So taking off the IIFE and using module scripts is not a feasible workaround for us.

These are the sources for the variants used:

Comment 3 Mihai Parparita 2020-06-09 10:42:30 PDT
Saam: It looks like you've looked into IIFE and TDZ-related performance issues in the past, any chance you could see if there's anything that could be done from the JSC side?
Comment 4 Radar WebKit Bug Importer 2020-06-09 12:14:23 PDT
Comment 5 Keith Miller 2020-07-14 16:13:59 PDT
I think you are seeing the same issue that came up in https://bugs.webkit.org/show_bug.cgi?id=199866. It seems like this is a more widespread problem that we should solve. I'll try to find time to work on it soon! Although, I no longer remember what the solution I had in mind back then was... 🤦‍♂️
Comment 6 Mihai Parparita 2020-10-20 23:25:33 PDT
Closing in favor of bug 199866 -- it's the same underlying issue and that one has more traction.

*** This bug has been marked as a duplicate of bug 199866 ***