tc39 / proposal-iterator.range

A proposal for ECMAScript to add a built-in Iterator.range()
https://tc39.es/proposal-iterator.range/
MIT License
487 stars 13 forks source link

Performance problem #69

Closed aquapi closed 5 months ago

aquapi commented 5 months ago
          Thank you for your feedback. We disagree, and believe there is significant value in providing built-in functions for common, non-trivial operations. Offering fundamentally new behavior is very useful, but making common patterns easy to write (and, by being built-in, easy to recognize and reason about in others' code) is also valuable.

Originally posted by @tabatkins in https://github.com/tc39/proposal-iterator.range/issues/68#issuecomment-2070854187

The introduction of this feature may create a lot of performance problem in the future, mainly because of it's over-usage.

Let's take a look at a simple example:

const arr = [1, 2, 3, 4, 5, 6, 7];

for (let i = 0, { length } = arr; i < length; ++i) {
    // Use arr[i] here
}

for (const item of arr) {
    // item
}

Believe it or not, the for of loop actually runs 5x slower (JITLess) and 16x slower (JIT) than the C-style for loop (Benchmark that yourself).

The reason for this is that for of relies on the iterator protocol, which on every iteration should create an object with a next() function, value and done key, which is significantly slower than just iterating normally.

And the reason why other language like Python or Go has this feature is:

Python

So for Python case, we already know that Python doesn't have a JIT, so to write optimized code in Python you have to rely on native code.

Let's take a simple example of calculating the sum of every element in an array. The fastest way to do it in Python (without external lib) is to:

sum(arr)

instead of doing a for loop:

result = 0
for item in arr:
    result += item

In the JavaScript case, JavaScript code can run as fast or sometimes faster than native code due to FFI overhead. Just take a look at a popular JavaScript URL router like Hono RegExpRouter.

Go

In Go case, it is pretty obvious since Go has a compiler and code like that maybe run faster than iterating normally.

aquapi commented 5 months ago

Performance problems often don't come from a single hotspot but from the code quality of the entire codebase, or comes from layers of abstractions that is 'easy to use' got introduced into the codebase.

tabatkins commented 5 months ago

Yes, we understand that the iterator protocol will generally be slower than hand-rolling iteration. This is not a blocker for any proposal in the language; on the contrary, we continue to add more APIs for dealing with iterators/generators, because it's a very useful, author-friendly feature. Performance is one important factor we take into consideration when designing and judging APIs, not the only one.

Unless there is a specific reason to believe that iterating numeric ranges is an actively harmful hot spot, such that it's important for the ecosystem that we encourage hand-rolling iteration, this isn't an issue for this proposal. And I don't believe there is any such reason.

aquapi commented 5 months ago

So you are saying that you will waste some memory for developer experience? That is not a good reason.

Explain to me why this feature should exist. @tabatkins

tabatkins commented 5 months ago

So you are saying that you will waste some memory for developer experience?

That is what I am saying, yes. All languages do this. Like I said, performance is one important aspect to consider for new features, not the only one.

Explain to me why this feature should exist.

No, I won't.