is an iterator allowed to reuse the same "state" object?
IIRC, it's not supposed to. The built-in iterators will return fresh objects each time, so there's no mutation hazard. Userland iterators can of course violate this, but at their peril.
No, it must return a new object every time.
See esdiscuss.org/topic/performance-of-iterator-next-as-specified for the last discussion on this.
On Apr 27, 2015, at 3:29 PM, Tab Atkins Jr. wrote:
IIRC, it's not supposed to. The built-in iterators will return fresh objects each time, so there's no mutation hazard. Userland iterators can of course violate this, but at their peril.
Well, that's not exactly what the ES2015 spec. says. The specification of the Iterator interface (people.mozilla.org/~jorendorff/es6-draft.html#sec-iterator-interface ) does not require that the next
method return a fresh object each time it it called. So a userland iterator would not be violating anything by reusing a result object.
However, the specifications for all ES2015 built-in iterators require that they return fresh objects.
None of the built-in consumers of the Iterator interface (for-of, Array.from, etc.) retain references to IteratorResult objects after testing for done
and accessing the value
, so semantically they don't care whether the ResultObject is reused. However, such reuse might preclude some otherwise plausible engine level optimizations.
You would hope that the engines might be able to create these objects on the stack but I don't think anyone does that yet and the result is a flood of eden objects.
I would like to know I'm wrong about this.
did you see esdiscuss.org/topic/performance-of-iterator-next-as-specified#content-15
A really good optimizing jit should be able to inline the 'next' call, recognize that the IterationResult object doesn't escape (it knows this for for-of loops) and not do an allocation at all.
I missed it, thanks. I know things will improve in time but I'm just coming from a discussion with folks complaining about the performance of generators and GC overhead in real code with Chrome and Firefox relative to simple hand written loops.
Note that there is a huge difference between optimising iterators (in particular, for-of), and optimising generators. I expect that VMs will start getting better on the former relatively soon, for iterators that are not generators. Making generators fast is a much more complicated problem.
But in either case, escape analysis and object allocation elimination can avoid the flood of eden objects John cited, right?
I'm inferring your comment about generator optimization hardship has to do with a function that yields -- whose CFG has multiple entry points and whose activation record must live in the heap.
On 29 April 2015 at 18:37, Brendan Eich <brendan at mozilla.org> wrote:
But in either case, escape analysis and object allocation elimination can avoid the flood of eden objects John cited, right?
Yes, together with inlining.
? I'm inferring your comment about generator optimization hardship has to do
with a function that yields -- whose CFG has multiple entry points and whose activation record must live in the heap.
Yes, the biggest challenge perhaps is not even generator CFGs per se, but getting inlining to work with them, which is necessary to take advantage of escape analysis.
On Wed, Apr 29, 2015 at 5:41 PM, Andreas Rossberg <rossberg at google.com> wrote:
Yes, the biggest challenge perhaps is not even generator CFGs per se, but getting inlining to work with them, which is necessary to take advantage of escape analysis.
Since the objects to be eliminated here are not created in the body of the generator-function, an implementation could create those objects in an inline-able .next() method, and thus eliminate the object even if none of the generator code can be inlined. Pseudocode:
Generator.prototype.next = function next(arg) {
var value = INTERNALS.runGenerator(this, arg);
var done = INTERNALS.generatorIsDone(this);
return {value, done};
};
But this too can interfere with other optimizations. Your broader point about generator optimization certainly stands.
By which I mean the object that returns the current value and "done" state?