Closed
Bug 1336862
Opened 9 years ago
Closed 9 years ago
Iterating over a JS object for its values allocates temporary garbage?
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
RESOLVED
WORKSFORME
People
(Reporter: jujjyl, Unassigned)
Details
Attachments
(1 file)
|
197.19 KB,
image/png
|
Details |
With Emscripten and asm.js/wasm, we are actively optimizing to generate as little garbage as is necessary to avoid generating GC stuttering that can impact smoothness of WebGL animations.
Here is something odd I'm seeing which I don't quite understand:
In our OpenAL audio backend implementation, we have a map of "integer ID" -> "audio source" objects for audio items that are currently playing, see https://github.com/kripken/emscripten/blob/master/src/library_openal.js#L261
When a new audio source is created, it is added to the src dictionary, at
https://github.com/kripken/emscripten/blob/master/src/library_openal.js#L374
When an audio source is finished, it is 'delete'd from the dictionary, at
https://github.com/kripken/emscripten/blob/master/src/library_openal.js#L360
At each animation frame, we need to update each audio source for its parameters, which is done here:
https://github.com/kripken/emscripten/blob/master/src/library_openal.js#L40
The surprising thing is that this last line 40 generates temporary garbage each frame as indicated by the DevTools Performance profiler with its excellent "Record Allocations" tool (this tool is disabled by default, enable it by ticking the checkbox at the gear icon on the right in DevTools Performance panel).
If I change the 'context.src' dictionary to a flat array, that avoids generating any temporary garbage and we get to run fully garbage clean. (this line is the last of the remaining "running" garbage allocations at each rendered frame in the tested codebase)
Is it expected that iterating a "for x in {...}" should generate temporary GC-able objects, and "for(var i = 0; i < [...]; ++i)" does not?
| Reporter | ||
Comment 1•9 years ago
|
||
Here is an illustration of what the Allocations tool shows on the given line.
Comment 2•9 years ago
|
||
(In reply to Jukka Jylänki from comment #0)
> Is it expected that iterating a "for x in {...}" should generate temporary
> GC-able objects, and "for(var i = 0; i < [...]; ++i)" does not?
Yes we allocate an iterator object (PropertyIteratorObject, a JSObject) that holds a pointer to a malloc NativeIterator.
| Reporter | ||
Comment 3•9 years ago
|
||
Thanks - is there a decent way to iterate such an object without generating temporary garbage? Or should I ideally use arrays for these types of scenarios?
Comment 4•9 years ago
|
||
I don't think there's a decent way that does not generate temporary garbage. The ES2015 iterator protocol (for-of loops) may create even more garbage because it returns a {done, value} object each iteration :( We sometimes optimize this away in the JIT but I wouldn't rely on that.
Using an object as hashmap and using delete is also relatively slow/inefficient. You could use Map but iterating that will also create garbage, so arrays are probably the best option...
| Reporter | ||
Comment 5•9 years ago
|
||
Right'o, I think can do away with maps and use arrays and implement a linked list of actively playing sound sources for per-frame iteration. It's a bit clumsy, but should be doable. Thanks!
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → WORKSFORME
You need to log in
before you can comment on or make changes to this bug.
Description
•