Performance of iterator .next() as specified

David Bonnet david at bonnet.cc
Sat Jul 11 14:31:25 UTC 2015


Sorry for bringing this up again, especially now that the specification has been finalised. However, I can’t really understand the rationale behind the design of `Iterator.next()`.

There are at least three possible options for the behaviour of `Iterator.next()`:
1. Returning a value and throwing `StopIteration` when done.
2. Returning {value, done} object with `done = true` when done.
3. Returning a value and returning `Symbol.iterationDone` when done.

I understand that option 1 would require trapping the exception.

Option 2 would require creating an object at each call, which as discussed in this thread, would require non-trivial optimisations.

Option 3, however, seems IMHO to have no caveats, and would require adding another symbol (`Symbol.iterationDone`) along with `Symbol.iterator`.

So why was option 2 chosen? Why not option 3? All I could find is a discussion that still refers option 1:
http://wiki.ecmascript.org/doku.php?id=harmony:iterators

Cheers,
David


Katelyn Gadd kg at luminance.org wrote on Sun Feb 15 02:06:51 PST 2015:

> As specified, iterator .next() seems to be required to return a new
> object instance for each iteration.
> 
> In my testing (and in my theory, as an absolute) this is a real
> performance defect in the spec and it will make iterators inferior to
> all other forms of sequence iteration, to the extent that they may end
> up being used very rarely, and developers will be biased away from Map
> and Set as a result.
> 
> The issue here is that the new object requirement means that every
> iteration produces GC pressure. I think that past APIs with this
> problem (for example TypedArray.set) have proven that 'a sufficiently
> smart VM can optimize this' is not representative of real VMs or real
> use cases.
> 
> In the specific case of .next(), the method returning a new object on
> every iteration does not produce any actual improvement to usability:
> There is no realistic use case that requires saving multiple next()
> results from the same sequence, as the sequence itself represents (at
> least in most cases) a container or generated value sequence that is
> fully reproducible on demand.
> 
> I think allowing (or requiring) implementations to return the same
> object instance from every .next() call, or perhaps as a usability
> compromise, reusing a pair of objects on a round-robin basis (so that
> you can keep around the current and prior result) would be a very good
> decision here.
> 
> In my testing Map and Set are outperformed by a trivial Object or
> Array based data structure in every case, *despite the fact* that
> using an Object as a Map requires the use of Object.keys() to be able
> to sequentially iterate elements. The cost of iterator.next() in v8
> and spidermonkey is currently extremely profound and profiling shows
> all the time is being spent in object creation and GC. (To be fair,
> self-hosting of iterations might improve on this some.)
> 
> Oddly enough, I consider the ES iterator spec to be a big improvement
> over C#'s IEnumerable, in terms of usability/API. But this is an area
> where it is intrinsically worse performance-wise than IEnumerable and
> that's unfortunate.
> 
> -kg


More information about the es-discuss mailing list