Status: New
Owner: ----
New issue 3650 by [email protected]: for x in y de-optimizations
https://code.google.com/p/v8/issues/detail?id=3650
Although it is known that `for (x in y) { }` will de-opt if `y` isn't
safely enumerable, it is still a very common perf issue to see in the wild
and typically the most egregious runtime induced slowdowns.
Alternatives exist, but unfortunately each alternative presents issues.
leaks low level ideas into a developers work-flow
Object.keys is limited to own Properties
Object.keys has stricter input requirements (x in y works with null,
undefined, numbers, NaN etc)
Object.keys allocates an intermediate array (can't bailout early)
means additional guards must exist. example: emberjs/ember.js#9386
writing your own helper that returns all properties isn't aware of
mutations during enumeration
your own helper function that returns all properties is again susceptible
to the inlining bailout poisoning
each above method has different performance implications
more....?
An example:
For example in chance.js, having the knowledge of branching to the "safe"
enumeration mechanism for the given object (Object.keys for an object, and
a for loop for an array) resulted in 28x performance improvement.
victorquinn/chancejs#88
Also, as a function instance is shared (and its optimized state is as well)
a library provided function such as `merge` can easily be poisoned causing
application wide performance issues.
Another Example:
emberjs/ember.js#5645 in ember, I noticed it was quite common for unrelated
parts of the framework to poison shared functions causing framework wide
bailouts. The most common of these was related to `for (var x in y)` one
such example was `Ember.merge`
given the obvious way to write merge.
function merge(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return b;
}
It took 1 slow-mode object or array `b` to cause some app wide slowdowns.
This was due mostly to inlining bailouts, which often resulted in entire
chunks of code being marked as not optimizable.
Knowing this, I was able to re-write Ember.merge to be resilient to such
poisoning.
function merge(a, b) {
var keys = Object.keys(b);
var key;
for (var i = 0, l = keys.length; i < l; i++) {
key = keys[i];
a[key] = b[key];
}
return b;
}
A third example:
Just another set of optimizations where `for (x in y) { } ` was
contributing to the performance issues.
emberjs/ember.js#5559
Conclusion:
In each example, a scenario specific solution resulted in tremendous
performance improvements. These unfortunately relied on relatively deep
understanding of the underlying platform and the resulting solutions had
considerably more caveats and nearly where always followed up with one or
more bug-fixes.
Although good performance is possible, having to know which levers to pull
to align with that platforms preference is unfortunate. Even worse, making
the wrong choice would very poison the larger system.
--
You received this message because this project is configured to send all
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.