Skip to content

[BUGFIX beta] Optimization in .keys#12950

Merged
rwjblue merged 1 commit into
emberjs:masterfrom
marijaselakovic:master
Feb 12, 2016
Merged

[BUGFIX beta] Optimization in .keys#12950
rwjblue merged 1 commit into
emberjs:masterfrom
marijaselakovic:master

Conversation

@marijaselakovic
Copy link
Copy Markdown
Contributor

Hi,

I spotted two locations where for-in loops can be refactored to Object.keys and for loop (similarly as in 53b9f19).

Results of running tests suites in Chrome 42 with original version:

Tests completed in 58335 milliseconds.13213 assertions of 13213 passed, 0 failed.

And with modified version:

Tests completed in 54474 milliseconds.13213 assertions of 13213 passed, 0 failed.

If you use some performance benchmark it would be interesting to try.

@rwjblue
Copy link
Copy Markdown
Member

rwjblue commented Feb 11, 2016

Can you prefix this commit with [BUGFIX beta] so that we can pull that into the beta branch?

@marijaselakovic marijaselakovic changed the title Optimization in .keys [BUGFIX beta] Optimization in .keys Feb 11, 2016
Comment thread packages/ember-metal/lib/mixin.js Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be pre allocated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var ret = Object.keys(keys), without for loop?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I believe that would work.

@stefanpenner
Copy link
Copy Markdown
Member

Its worth noting, that for of vs Object.keys isn't always cut and dry. Lots of really annoying trade-offs.

@rwjblue
Copy link
Copy Markdown
Member

rwjblue commented Feb 11, 2016

This looks good. Can you squash all the commits down into one?

Comment thread packages/ember-metal/lib/mixin.js Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krisselden can we safely omit the own clause here ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefanpenner - Doesn't Object.keys only return own properties? In other words, the proposed change does not change the semantics of what it was doing before...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

semantically the output values would be the same (although sort order can differ depending on many things...), but that isn't why i asked. I should have been clearer as to why.

If props is always a fast object and never has inherited properties (which maybe we cant guarentee) then for (let key in props) { ret[key] = true; } would be by far the fastest option.

Object.keys is the safe bet here though

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, I see what you mean, thanks for explaining!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just thought of it while reading, and thought maybe we should have a quick discussion.

refactor for-in loop

[BUGFIX beta] Avoiding redundant for loop
@marijaselakovic
Copy link
Copy Markdown
Contributor Author

Ok, I squashed all commits into single one. Regarding semantic equivalence, indeed for in+hasOwnProperty check is same as Object.keys. Regarding performance of both cases, if you try to track compiler optimizations in for example V8, you can easily see that V8 disables optimization of for-in loop and reports the following: > ForInStatement is not fast case

In general, the actual performance improvement depends on the input. If .keys function iterates over objects with large number of properties, Object.keys might be performance wise.

@rwjblue
Copy link
Copy Markdown
Member

rwjblue commented Feb 12, 2016

@stefanpenner - I'm going to land this for now (it is a clear improvement), and continue following up with @krisselden about the remaining question.

rwjblue added a commit that referenced this pull request Feb 12, 2016
[BUGFIX beta] Optimization in .keys
@rwjblue rwjblue merged commit 73cbf24 into emberjs:master Feb 12, 2016
@rwjblue
Copy link
Copy Markdown
Member

rwjblue commented Feb 12, 2016

Thank you @marijaselakovic!

@stefanpenner
Copy link
Copy Markdown
Member

@marijaselakovic I'm confused, how does that differ from my comment. If we know the input is always on the happy path, for in is actually better. My question was largely, can we be sure of that and if not can we make changes to ensure that.

@marijaselakovic
Copy link
Copy Markdown
Contributor Author

The case I am aware of, when for in and Object.keys perform equally in terms of performance is when you have object without inherited properties and properties that are not dynamically generated, so situation like: var obj={a:1,b:2,c:3}; I am not aware of the case when for in loop is actually better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants