-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Substantially optimize coordinates.parse #3579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/utils/coordinates.js
Outdated
| return vecParseFloat(vec); | ||
| for (var i = 0; i < coordinateKeys.length; i++) { | ||
| var key = coordinateKeys[i]; | ||
| if (coordinate.length > i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably more clear if you do if (coordinate[i] !== undefined)
src/utils/coordinates.js
Outdated
| vec[key] = parseFloat(coordinate[i], 10); | ||
| } else { | ||
| var defaultVal = defaultVec && defaultVec[key]; | ||
| if (defaultVal !== undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Early return preferable:
if (defaultVal === undefined) { continue; }
vec[key] = parseIfString(defaultVal);
src/utils/coordinates.js
Outdated
| vec.z = coordinate[2] || defaultVec && defaultVec.z; | ||
| vec.w = coordinate[3] || defaultVec && defaultVec.w; | ||
| return vecParseFloat(vec); | ||
| for (var i = 0; i < coordinateKeys.length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit more compact using forEach
coordinateKeys.forEach(function (key, i) {
if (coordinate[i] !== undefined) {
vec[key] = parseFloat(coordinate[i], 10);
} else {
if (defaultVal === undefined) { return; }
vec[key] = parseIfString(defaultVal);
}
}
src/utils/coordinates.js
Outdated
| var warn = debug('utils:coordinates:warn'); | ||
|
|
||
| // Order of coordinates parsed by coordinates.parse. | ||
| var coordinateKeys = ['x', 'y', 'z', 'w']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capitalize since it's a const COORDINATE_KEYS
|
Some of the unit tests are failing with the change. |
|
Thanks for the PR. It looks good. One thing that you might want to consider. If you are calling init: function () {
this.yourComponentData = {coords: {x: 0, y: 0, z:0}, enabled: true};
},
tick: function () {
this.yourComponentData.coords.x += 1;
this.el.setAttribute('your-component', this.yourComponentData);
} |
|
If you are in a tick, better to just avoid setAttribute altogether. We should have the raycaster component update the origin/direction directly. We already do the object reuse, that only saves on parsing. |
|
I made the style changes you suggested. The test failure was a real bug; it was the new version doing a bad job of handling the empty string or a string with all spaces as input. It should line up now. Performance still seems equally good. Thanks for the advice about reusing the same object, that advice could really be worth its weight in gold for us -- if not here, in other places. I'm not sure anyone on our team realized that! |
|
Thank you. First PR achievement unlocked 🎉 Congrats! |
coordinates.parsewinds up accounting for a moderate amount of time if you do per-frame updates of attributes containing new string or object coordinates. (In our project, an example was a raycaster component which we updated with a new direction and origin each frame.) This change makes it between 2x and 10x faster in both the string-input and object-input cases in Firefox and Chrome (depending on input characteristics) while being more or less equally straightforward.Here's a JSPerf comparing the old and new versions.
There's one edge case I'm worried about. In the old version, if you gave the input
{x: 1, y: "2", splatoon: "42", "whiz": "bang"}, it would return{x: 1, y: 2, splatoon: 42, whiz: NaN}. That is, it would parse any string keys at all in the input, even ones that it didn't know anything about, and even ones that aren't floats. That behavior seems strange to me, it didn't seem documented anywhere, and no test was exercising it, but it's true. If that behavior is important, then let me know and I'll hack it back in.