Open Bug 1807895 Opened 2 years ago Updated 1 year ago

Slow performance of `new Set(anotherSet)`

Categories

(Core :: JavaScript Engine, defect, P3)

Firefox 108
defect

Tracking

()

UNCONFIRMED

People

(Reporter: james.mountain, Unassigned)

References

(Blocks 2 open bugs)

Details

(Whiteboard: [sp3])

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36

Steps to reproduce:

const arr = new Array(1000 * 1000).fill(0).map((_, i) => i)
const s1 = new Set(arr)

// Performance of:
new Set(s1)

// Is ~40% slower than:
new Set(arr)

// And is ~10% slower than:
new Set([...s1])

// And is ~10% slower than:
const s2 = new Set()
s.forEach(v => s2.add(v))

https://jsbench.me/2qlc7mg84t/1

Actual results:

Slow performance when passing an existing set into the constructor of a new set.

Expected results:

Comparable performance to passing an array (or better).

The Bugbug bot thinks this bug should belong to the 'Core::Performance' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.

Component: Untriaged → Performance
Product: Firefox → Core
Component: Performance → JavaScript Engine

We definitely have a specific optimization path that we use only for creating a set from an array, which explains this performance gap.

While it would be nice to improve this, without evidence this is a frequent issue sites run into, I'll triage this at a relatively low priority.

Severity: -- → S4
Priority: -- → P3

In ui frameworks (e.g. React), it is necessary to return a new object to trigger a render. Returning a mutated Set (e.g. via s.add) will not cause a re-render. The slow performance of cloning an existing Set in mozilla means that Set is useless for use with modern ui frameworks.

Comparing performance (of the benchmark posted above) with Safari:

new Set(s)
// safari: 15 op/s
// firefox: 4.4 op/s

new Set(a)
// safari: 8.49 op/s
// firefox: 8.27 op/s

To add. The performance difference is even worse with smaller sets of data. E.g. with 1000 items in the set/array:

new Set(s)
// 13,000 op/s

new Set(a)
// 27,000 op/s

Depends on: 1808675

I'll bump the severity here: Will be interesting to see if Bug 1808675 aids appreciably or not.

Severity: S4 → S3

Bug 1432565 has some old patches to improve this use case.

Whiteboard: [sp3]
You need to log in before you can comment on or make changes to this bug.