With ES6 features landing quickly in native browsers and readily available for use through Babel and Traceur, it seemed like it was time to look not just at support, but also the performance impact of using these features under the current implementations.
While there is great promise for the future, the picture of ES6 feature performance today is very muddled and depends on the specific feature being used. Some such as bindings and simple arrow/destructuring are ready for use today, others such as generators and tagged template strings might require analysis before using.
The standard warnings of premature optimization and recommendations to profile your own code apply to the comments here. These tests are very micro in their scope and might not be representative of your particular use case. It’s also possible that the ES6 version is fast enough for your use case and is not worth additional time spent refactoring to a more complicated but faster implementation.
Results
Arrow Function
Arrow functions invocation has little performance impact under transpilers. Their native implementation under Firefox is 4070x slower for calls than the equivalent ES5 operation. Internet Explorer’s performance is approximately that of ES5.
Arrow function declaration on the other hand is slightly slower than the most optimized ES5 implementation, under most environments. Here too Firefox’s implementation shows a large performance hit and IE shows a slight performance hit.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
arrow
tests

babel 
1.3x slower 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
1.2x faster 
Identical 
traceur 
1.3x slower 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
1.3x faster 
Identical 
es5bind 
10x slower 
15x slower 
19x slower 
14x slower 
20x slower 
6x slower 
6x slower 
7x slower 
4x slower 
2.6x slower 
3x slower 
es6 





38x slower 
41x slower 
52x slower 

Identical 

arrowargs
tests

babel 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
1.2x faster 
Identical 
traceur 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
1.2x faster 
Identical 
es6 

2.9x slower 



64x slower 
89x slower 
68x slower 

1.3x faster 

arrowdeclare
tests

babel 
1.3x slower 
1.3x slower 
Identical 
Identical 
Identical 
8x slower 
10x slower 
13x slower 
2.3x slower 
1.6x slower 
1.4x slower 
traceur 
1.3x slower 
1.3x slower 
Identical 
Identical 
Identical 
5x slower 
7x slower 
8x slower 
2.3x slower 
1.4x slower 
1.4x slower 
es6 

Identical 



53x slower 
78x slower 
78x slower 

1.3x slower 

Issues:
Classes
With classes we start to see some differences in behaviors. Traceur and the V8 native implementation operate at partity with the ES5 tests when looking at instantiation. Babel’s implementation does suffer a 1.560x performance hit for the operations tested. When compiling using Babel’s loose mode, the hit is lessened to 8x.
The super
keyword has some fairly large performance issues under all implementations, with the best case being 3x slower and the worst case being 60x slower than the respective baselines. V8’s native implementation also sees a 1520x performance hit.
Babel’s loose implementation of super
is akin to that of the ES5 implementation, utilizing C.prototype.bar.call(this)
rather than the slower getPrototypeOf
lookup operation that while more accurate technically, incurs an additional cost. This is controlled by the es6.classes
parameter but Babel’s authors cite a number of warnings with this flag that may impact compatibility when migrating code to native implementations.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
classes
tests

babel 
2.3x slower 
1.5x slower 
1.3x slower 
1.4x slower 
1.3x slower 
27x slower 
26x slower 
30x slower 
1.4x slower 
1.5x slower 
Identical 
babelloose 
2.3x slower 
1.5x slower 
1.3x slower 
1.4x slower 
1.3x slower 
6x slower 
6x slower 
8x slower 
1.3x slower 
2.4x slower 
Identical 
traceur 
Identical 
Identical 
Identical 
Identical 
Identical 
1.5x slower 
1.7x slower 
1.8x slower 
Identical 
Identical 
Identical 
es6 

Identical 
Identical 
Identical 
Identical 






super
tests

babel 
24x slower 
60x slower 
52x slower 
48x slower 
45x slower 
60x slower 
62x slower 
61x slower 
24x slower 
24x slower 
16x slower 
babelloose 
2.0x slower 
1.7x slower 
1.7x slower 
1.7x slower 
1.7x slower 
5x slower 
5x slower 
5x slower 
3x slower 
3.0x slower 
1.2x slower 
traceur 
12x slower 
26x slower 
18x slower 
18x slower 
18x slower 
26x slower 
30x slower 
27x slower 
10x slower 
12x slower 
11x slower 
es6 

14x slower 
19x slower 
21x slower 
18x slower 






Issues:
Enhanced Object Literals
Object literal extensions generally provide an overhead of up to 147x the baseline. Under the transpiler implementations this is due to the use of defineProperty
rather than the much more optimized field assignment. This is done to bullet proof code from potential edge cases discussed here. Loose mode is effectively the same as the ES5 implementation as of 5.6.7

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
objectliteralext
tests

babel 
4x slower 
60x slower 
72x slower 
71x slower 
80x slower 
1.8x slower 
1.6x slower 
1.6x slower 
2.6x slower 
2.0x slower 
2.5x slower 
babelloose 
Identical 
12x slower 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
traceur 
8x slower 
120x slower 
143x slower 
122x slower 
144x slower 
3x slower 
3x slower 
2.9x slower 
5x slower 
4x slower 
4x slower 
es6 

25x slower 

23x slower 
26x slower 
1.4x slower 
1.5x slower 
1.3x slower 

Identical 

Issues:
Template Strings
Template strings are a mixed bag. In the basic form, transpilers are able to hit parity with the baseline implementation under most environments. The native implementations are hit or miss. Under Chrome they execute at half the speed and under Firefox up to 650x slower.
Tagged template strings unfortunately do not have such a nice outlook. Their performance ranged from 2x slower for IE’s native implementation to 2000x slower for Babel’s implementation under Firefox. Babel’s loose implementation (es6.templateLiterals
) lessens much of the overhead of this operation, at the cost of not having a fully compliant String.raw
implementation.
Issues:

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
template_string
tests

babel 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
1.5x faster 
1.4x faster 
Identical 
traceur 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
es6 

Identical 
2.0x slower 
2.0x slower 
1.9x slower 
627x slower 
622x slower 
591x slower 

1.3x faster 

template_string_tag
tests

babel 
567x slower 
578x slower 
722x slower 
755x slower 
820x slower 
2395x slower 
2349x slower 
2028x slower 
90x slower 
82x slower 
61x slower 
babelloose 
2.0x slower 
1.6x slower 
1.7x slower 
1.6x slower 
1.8x slower 
94x slower 
87x slower 
84x slower 
1.4x slower 
1.4x slower 
2.0x slower 
traceur 
7x slower 
13x slower 
17x slower 
13x slower 
16x slower 
346x slower 
307x slower 
261x slower 
13x slower 
11x slower 
8x slower 
es6 

8x slower 
9x slower 
13x slower 
9x slower 
68x slower 
64x slower 
59x slower 

Identical 

Destructuring
For destructuring, the average use case effectively matches that of the ES5 counterpart. Unfortunately complex use cases, particularly those around array destructuring, often have large performance overhead. Under Babel an unoptimized helper is used to access the data and under Traceur an entire iterator structure is created, both of which provide fairly substantial memory and CPU overhead over the simple array accessor logic that hand coded ES5 can utilize. Loose mode is effectively the same as the ES5 implementation.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
destructuring
tests

babel 
1.8x slower 
1.4x slower 
1.4x slower 
1.2x slower 
1.3x slower 
24x slower 
22x slower 
26x slower 
3x slower 
5x slower 
2.2x slower 
babelloose 
1.2x faster 
Identical 
Identical 
1.2x faster 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
traceur 
26x slower 
13x slower 
12x slower 
10x slower 
11x slower 
163x slower 
152x slower 
176x slower 
57x slower 
25x slower 
8x slower 
es6 





170x slower 
148x slower 
185x slower 


Identical 
destructuringsimple
tests

babel 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
10x slower 
1.2x slower 
Identical 
traceur 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
1.3x slower 
Identical 
es6 





Identical 
Identical 
Identical 


Identical 
Issues:
Default Parameters
Default parameters were universally slower for all transpiler implementations. They effectively compile to the same thing, utilizing the arguments
object to set a local variable vs. using a named paramemter. This appears to be unoptimzed under all engines and consequently performance was 42000x slower. Sadly, this is required in order to properly implement the fn.length
behavior defined by the spec:
NOTE The ExpectedArgumentCount of a FormalParameterList is the number of FormalParameters to the left of either the rest parameter or the first FormalParameter with an Initializer. A FormalParameter without an initializer is allowed after the first parameter with an initializer but such parameters are considered to be optional with undefined as their default value.
These scaled numbers should be taken in context. The ES5 equivalents are highly optimized, Firefox pushing over 833 million operations a second in one test, so the net performance of the transpiled versions may very well be sufficient for most use cases, particularly those not on the hot path.
The only native implementation, Firefox, performed identically to the ES5 implementation.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
classes
tests

babel 
2.3x slower 
1.5x slower 
1.3x slower 
1.4x slower 
1.3x slower 
27x slower 
26x slower 
30x slower 
1.4x slower 
1.5x slower 
Identical 
babelloose 
2.3x slower 
1.5x slower 
1.3x slower 
1.4x slower 
1.3x slower 
6x slower 
6x slower 
8x slower 
1.3x slower 
2.4x slower 
Identical 
traceur 
Identical 
Identical 
Identical 
Identical 
Identical 
1.5x slower 
1.7x slower 
1.8x slower 
Identical 
Identical 
Identical 
es6 

Identical 
Identical 
Identical 
Identical 






defaults
tests

babel 
17x slower 
11x slower 
11x slower 
9x slower 
8x slower 
1842x slower 
2051x slower 
2043x slower 
229x slower 
72x slower 
4x slower 
traceur 
16x slower 
12x slower 
12x slower 
10x slower 
9x slower 
1759x slower 
2305x slower 
1974x slower 
210x slower 
73x slower 
4x slower 
es6 





Identical 
Identical 
Identical 



Rest Parameters
Rest parameters are as fast or faster than the ES5 equivalent under almost all implementations. Native implementations provided a performance boost up to 40x (with the exception of V8 where it causes a known deoptimization). Use them with a transpiler. They’re great. Death to arguments
.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
rest
tests

babel 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
2.0x slower 
1.5x slower 
Identical 
traceur 
Identical 
1.5x faster 
1.2x faster 
1.2x faster 
1.2x faster 
31x faster 
34x faster 
27x faster 
2.4x slower 
1.6x slower 
1.3x faster 
es6 

3x slower 



40x faster 
42x faster 
32x faster 

8x faster 

Spread Parameters
Under Babel, spread parameters for arrays perform identically to the ES5 counterpart as they are effectively both an apply
call. Under Traceur and all of the native implementations the implementations are 1.3x to 17x slower.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
spread
tests

babel 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
traceur 
13x slower 
6x slower 
5x slower 
6x slower 
6x slower 
2.7x slower 
3x slower 
3x slower 
9x slower 
712x slower 
17x slower 
es6 





3x slower 
4x slower 
4x slower 

1.3x slower 
2.5x slower 
spreadgenerator
tests

babel 
150x slower 
55x slower 
58x slower 
66x slower 
71x slower 
153x slower 
143x slower 
157x slower 
656x slower 
423x slower 
64x slower 
babelloose 
114x slower 
46x slower 
41x slower 
45x slower 
53x slower 
60x slower 
60x slower 
61x slower 
28x slower 
51x slower 
22x slower 
traceur 
27x slower 
10x slower 
9x slower 
10x slower 
13x slower 
11x slower 
10x slower 
11x slower 
15x slower 
1551x slower 
9x slower 
es6 





7x slower 
8x slower 
7x slower 



spreadliteral
tests

babel 
Identical 
Identical 
Identical 
Identical 
Identical 
1.2x slower 
Identical 
1.2x slower 
3x slower 
1.7x slower 
2.0x slower 
traceur 
6x slower 
3.0x slower 
2.1x slower 
2.5x slower 
2.3x slower 
6x slower 
5x slower 
5x slower 
26x slower 
451x slower 
9x slower 
es6 





8x slower 
7x slower 
8x slower 

1.8x slower 
3x slower 
Let + Const
let
and const
bindings were pretty much identical across the board. While these don’t offer performance improvements (yet), they shouldn’t negatively impact performance.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
bindings
tests

babel 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
traceur 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
Identical 
1.3x faster 
Identical 
es6 
Identical 
Identical 
Identical 
Identical 
Identical 
2.3x slower 
Identical 
Identical 
1.3x slower 
Identical 

For..of
for..of
is universally slower, ranging from 3 to 20x slower for array iteration over classical array iteration. When iterating over an object with a custom iterator, the performance is also much slower than for..in
iteration with hasOwnProperty
checks.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
forofarray
tests

babel 
21x slower 
8x slower 
8x slower 
9x slower 
9x slower 
14x slower 
20x slower 
19x slower 
15x slower 
489x slower 
7x slower 
babelloose 
Identical 
Identical 
Identical 
Identical 
Identical 
1.4x slower 
1.7x slower 
1.7x slower 
1.3x slower 
Identical 
1.8x slower 
traceur 
12x slower 
7x slower 
7x slower 
8x slower 
8x slower 
26x slower 
31x slower 
32x slower 
9x slower 
6x slower 
6x slower 
es6 

6x slower 
6x slower 
8x slower 
8x slower 
5x slower 
7x slower 
7x slower 

2.9x slower 
4x slower 
forofobject
tests

babel 
10x slower 
7x slower 
8x slower 
9x slower 
6x slower 
6x slower 
6x slower 
5x slower 
60x slower 
11x slower 
6x slower 
babelloose 
10x slower 
6x slower 
7x slower 
9x slower 
7x slower 
4x slower 
4x slower 
4x slower 
6x slower 
449x slower 
6x slower 
traceur 
8x slower 
7x slower 
8x slower 
9x slower 
7x slower 
9x slower 
10x slower 
9x slower 
5x slower 
4x slower 
4x slower 
es6 

6x slower 
7x slower 
8x slower 
6x slower 
3x slower 
3x slower 
3x slower 

3x slower 

Generators
Much like for..of
, generators are also quite a bit slower than a raw ES5 implementation of the iterable protocol, with performance ranging from 10x to 750x slower. There is hope here as the V8 implementation achieves parity with the ES5 implementation.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
generator
tests

babel 
601x slower 
65x slower 
67x slower 
63x slower 
69x slower 
754x slower 
723x slower 
716x slower 
79x slower 
499x slower 
78x slower 
traceur 
77x slower 
10x slower 
10x slower 
10x slower 
12x slower 
48x slower 
50x slower 
46x slower 
18x slower 
112x slower 
10x slower 
es6 

Identical 
1.2x slower 
Identical 
Identical 
22x slower 
20x slower 
19x slower 



Issues:
Maps and Sets
Map
and Set
all have insert performance that is about 10x slower for a moderately sized data set. All of the implementations show massive improvement on the lookup operations, with Firefox’s native implementation showing a 200x speed increase for a dataset of size 500.
Traceur appears to delegate to the native implementation via their polyfill where possible so performance is closely linked to improvements in the native layer. In runtime mode, Babel does not appear to delegate and performance suffers as a result. Babel’s polyfill mode should behave as Traceur does but this was not directly tested.
Take caution with these numbers. The tests use a data set of size 500 and other data sets will have varying performance but it appears that these features are ready for general use if you have many reads and few writes or need to have objects as keys.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
mapset
tests

babel 
13x slower 
3.0x slower 
5x slower 
5x slower 
3.0x slower 
105x slower 
12x slower 
15x slower 
60x slower 
19x slower 
79x slower 
traceur 
5x slower 
Identical 
2.2x slower 
2.3x slower 
1.6x slower 
20x slower 
2.5x slower 
2.4x slower 
28x slower 
2.2x slower 
16x slower 
es6 
5x slower 
Identical 
2.2x slower 
2.3x slower 
1.6x slower 
21x slower 
2.2x slower 
2.7x slower 
28x slower 
2.2x slower 
15x slower 
Promises
Promises are across the board faster with both the polyfill and native implementations. This particular benchmark is dubious as it’s both async and inheriently tied to long running behaviors where execution overhead has little impact.

node 
chrome 
firefox 
internet explorer 
safari 

0.10.39 
2.3.0 
43 
44 
45 
38 
39 
40 
11 
12 
8 
promises
tests

babel 
Identical 
Identical 
6x faster 
7x faster 
7x faster 
21x faster 
17x faster 
16x faster 
Identical 
1.2x slower 
3x faster 
traceur 
Identical 
Identical 
2.0x faster 
2.0x faster 
1.9x faster 
36x faster 
31x faster 
Identical 
Identical 
1.8x slower 
3x faster 
es6 

Identical 
2.0x faster 
2.0x faster 
1.9x faster 
37x faster 
29x faster 
Identical 

1.9x slower 
3x faster 
Testing methodology
For each of the ES6 features in question, a ES5 implementation of that functionality was written along with a ES6 version. It should be noted that the functionality is frequently the same, but in some cases the “common” vs. “correct” version was written, i.e. using x[key] = value
vs. defineProperty
which is faster but can be hit but a particular nasty edge case for those who deem it fun to extend Object.prototype
.
Babel, in both loose+runtime and runtime mode, and Traceur were then used to compile the ES6 version to a ES5 compliant version, utilizing the runtime over polyfill to maintain test isolation and avoid native implementations where possible.
All of these test instances were then benchmarked in the given JavaScript engine using Benchmark.js and then the operations per second compared to the ES5 implementation. Cross browser and cross execution comparisions are avoided as much as possible to isolate environmental issues when executing on VMs in the cloud.
All of this data, including any updates from more recent test runs is available at http://kpdecker.github.io/sixspeed/ and the test suite is available at https://github.com/kpdecker/sixspeed for review/feedback.
Takeaways
As noted above, these results might not be representative of your own application since they only test very small subsets of inputs and behaviors of these new features. If you are finding that you have performance issues with your code using these features, you should test them within your own environment to see what the actual behavior is.
While some of these features are a bit slow as of this writing, their performance should only improve as the native implementations mature and are optimized as real world use is applied to them. For the transpilers, there are some performance optimzations that can be made but much of the overhead they are experiencing is due to spec compliance, which they go to great lengths to achieve, but this comes with unfortunate overhead under ES5 implementations as they stand. Babel’s loose mode does offer a bit of a performance boost, but care must be taken when using loose mode as this could cause breakages when code is migrated to the standard native implementations.
Personally I intend to start using most of these features where they make sense but will avoid designing core APIs around these features (perhaps with the exception of Promises) until the native implementations have matured a bit.