Open Bug 1266140 Opened 9 years ago Updated 2 years ago

Object.keys 50% slower than for...in

Categories

(Core :: JavaScript Engine, defect, P3)

defect

Tracking

()

UNCONFIRMED
Webcompat Priority P3
Performance Impact low

People

(Reporter: leeoniya, Unassigned)

References

(Blocks 1 open bug)

Details

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:48.0) Gecko/20100101 Firefox/48.0 Build ID: 20160419030312 Steps to reproduce: Chrome, Edge, IE11 and IE10 perform the following benchmarks in approx the same time (or faster for Object.keys versions), while Firefox is 60% slower: // single-hash var hash = {}, key; for (var i = 0, len = 1e6; i < len; i++) { key = Math.random().toString(36).substring(4); hash[key] = true; } var x; console.time("for-in"); for (var i in hash) x = hash[i]; console.timeEnd("for-in"); console.time("for/keys"); for (var i = 0, keys = Object.keys(hash), len = keys.length; i < len; i++) x = hash[keys[i]]; console.timeEnd("for/keys"); // multi-hash var len = 1e3, hashes = Array(len), key; for (var j = 0; j < len; j++) { var hash = {}; for (var i = 0; i < len; i++) { key = Math.random().toString(36).substring(4); hash[key] = true; } hashes[j] = hash; } console.time("for-in (multi)"); for (var j = 0; j < len; j++) { hash = hashes[j]; for (var i in hash) x = hash[i]; } console.timeEnd("for-in (multi)"); console.time("for/keys (multi)"); for (var j = 0; j < len; j++) { hash = hashes[j]; for (var i = 0, keys = Object.keys(hash), len = keys.length; i < len; i++) x = hash[keys[i]]; } console.timeEnd("for/keys (multi)"); Actual results: 50% perf drop. Expected results: Faster or same perf.
I came across this bug as I was working on a small JS script to create fractals. I may be wrong but my suspicion is that the performance has less to do with Object.keys and more to do with how for loops are treated by Spidermonkey. Consider the following script: --------------------------------------------------------- var a,b; randomArray = (length, max) => [...new Array(length)] .map(() => Math.round(Math.random() * max)); var test = randomArray(1000000, 10000); console.time('oldfor'); for (var i = 0 ; i < test.length; i++) { b = test[i]; } console.timeEnd('oldfor'); console.time('newfor'); for (var t in test) { a = test[t];} console.timeEnd('newfor'); --------------------------------------------------------- On Edge, this produces: oldfor: 463.17ms newfor: 494.23ms On Firefox, this produces: oldfor: 826.65ms newfor: 652.41ms It's entirely possible that Object.keys accentuates this difference, but I couldn't be sure. I'll play around a little more tomorrow.
Whiteboard: [qf]
Whiteboard: [qf] → [qf:p3:fx67]

This creates a webcompat issue on mobile where the performance kills the experience. At the origin there is a coding mistake from the web developer of the site but Chrome gets away with it and Firefox freezes.
This is the profile https://share.firefox.dev/3G4i5pD

Webcompat Priority: --- → P3
Performance Impact: --- → P3
Whiteboard: [qf:p3:fx67]
Blocks: sm-js-perf
Severity: normal → S3
Priority: -- → P3
You need to log in before you can comment on or make changes to this bug.