Improve the performance of report name generation#12399
Conversation
|
I ran into some really fundamental problems with the optionlistutils, so I am putting this back into draft mode to see if I can figure it out. |
|
OK, I figured it out and this is good to go again. |
|
Durn conflicts :'( |
Beamanator
left a comment
There was a problem hiding this comment.
Overall code looking great, had only a few minor comments that are mainly NAB - will test now
| } | ||
| reportName = ReportUtils.getReportName(report, policies); | ||
| } else { | ||
| reportName = ReportUtils.getDisplayNameForParticipant(logins[0]); |
There was a problem hiding this comment.
Just wondering, why use logins[0] here instead of personalDetail.login like the following 2 lines?
src/libs/ReportUtils.js
Outdated
| } | ||
|
|
||
| /** | ||
| * Gets the personal details for a login by looking in the allPersonalDetails from Onyx. If it doesn't exist in Onyx, then a default object is constructed. |
There was a problem hiding this comment.
NAB
| * Gets the personal details for a login by looking in the allPersonalDetails from Onyx. If it doesn't exist in Onyx, then a default object is constructed. | |
| * Gets the personal details for a login by looking in the allPersonalDetails Onyx key. If it doesn't exist in Onyx, then a default object is constructed. |
There was a problem hiding this comment.
I see where you're going with the suggestion, but allPersonalDetails isn't actually an Onyx key. If you want the comment to reference the actual Onyx key, then it should say something like:
by looking in the ONYXKEYS.PERSONAL_DETAILS Onyx key.
The comment is currently referencing the local variable that the data from the Onyx key is stored in, so I think the comment is correct as originally authored.
There was a problem hiding this comment.
Ok definitely fair points! I'm still not a huge fan of the way the first sentence is worded, so how about this instead:
| * Gets the personal details for a login by looking in the allPersonalDetails from Onyx. If it doesn't exist in Onyx, then a default object is constructed. | |
| * Gets the personal details for a login by looking in the allPersonalDetails data from Onyx. If it doesn't exist in Onyx, then a default object is constructed. |
Mainly I don't like the allPersonalDetails bit, am I being too picky? Yes, maybe :D
There was a problem hiding this comment.
OK, I've updated this with a bit of a different suggestion and being slightly more verbose.
| // Normally, the spread operator would be used here to clone the report and prevent the need to reassign the params. | ||
| // However, this code needs to be very performant to handle thousands of reports, so in the interest of speed, we're just going to disable this lint rule and add | ||
| // the reportDisplayName property to the report object directly. | ||
| // eslint-disable-next-line no-param-reassign |
There was a problem hiding this comment.
Nifty 👍 I can't think of any downside to this, worst case is reportDisplayName stays on the report object even when it's not needed, but I can't see how that would cause any problems 👍
There was a problem hiding this comment.
Here we are 😁 This tricked us that we were using report.reportDisplayName (or report.displayName) across the App thinking it's a natural prop. This backfired once we started passing cloned reports to this function. Cloned reports are due to the use of withOnyx selector #21406
There was a problem hiding this comment.
I strongly disagree with allowing mutations into our code, it creates hard to debug bugs and is hard to track the states of objects.
There was a problem hiding this comment.
Now there is a second property getting mutated below this one:
Lines 112 to 113 in c32fb5a
There was a problem hiding this comment.
I'm fine with finding a way to remove the mutations as long as the code remains performant.
There was a problem hiding this comment.
I'm not totally sure but I think we can leave the mutation now since we are mutating a clone. I don't see much benefit in cloning a clone.
There was a problem hiding this comment.
I guess that makes it a bit better because we are only mutating the copy we pass down this tree, right?
App/src/pages/home/sidebar/SidebarLinksData.js
Lines 150 to 159 in fe8aeb8
Still a bad practice in react to mutate props in general, you have to follow up from where the prop is coming to verify that this is not causing more side effects and it is also hard to assure that things are getting rendered when they should down the line.
I'm fine with finding a way to remove the mutations as long as the code remains performant.
That is fair, do you know how to reproduce the performance issues?
There was a problem hiding this comment.
The best way to ensure it doesn't regress on performance is to add some timers around this code, and then time it before/after making the change.
|
Actually will probably wait to test till conflicts are resolved, so I don't have to retest :D |
tgolen
left a comment
There was a problem hiding this comment.
Updated with conflicts resolved!
src/libs/ReportUtils.js
Outdated
| } | ||
|
|
||
| /** | ||
| * Gets the personal details for a login by looking in the allPersonalDetails from Onyx. If it doesn't exist in Onyx, then a default object is constructed. |
There was a problem hiding this comment.
I see where you're going with the suggestion, but allPersonalDetails isn't actually an Onyx key. If you want the comment to reference the actual Onyx key, then it should say something like:
by looking in the ONYXKEYS.PERSONAL_DETAILS Onyx key.
The comment is currently referencing the local variable that the data from the Onyx key is stored in, so I think the comment is correct as originally authored.
|
Oops, just noticed this PR |
|
Shucksadoodle, I'm not able to test this on all platforms today, but most likely will be able to tomorrow 🙏 (Tested on web and so far that looks perfecto) |
|
|
@Beamanator looks like this was merged without the checklist test passing. Please add a note explaining why this was done and remove the |
|
99.9% sure I saw the green checkmark indicating all tests were passing 🙃 |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by @Beamanator in version: 1.2.24-0 🚀
|
|
🚀 Deployed to production by @yuwenmemon in version: 1.2.24-4 🚀
|
1 similar comment
|
🚀 Deployed to production by @yuwenmemon in version: 1.2.24-4 🚀
|
|
🚀 Deployed to production by @yuwenmemon in version: 1.2.24-4 🚀
|
|
This PR has been linked to a regression reported here: #12487 The fix was kind of simple and the mistake we made was that we changed a method signature and didn't update a usage. One thing we can learn from this is to be hyper vigilant about method signature changes and always double check that any usages of a function are updated. We also would have caught this automatically if we used some kind of type checking like TypeScript. |
|
Good catch @marcaaron , definitely good idea to be hyper vigilant about method signature changes, even when reviewing 👍 |






This speeds up the report name generation by about 200%. I tested this on an account with 4,000 reports. Before the change, it took 30ms to generate all the report names. After this change, it only takes 10ms.
Fixed Issues
$ #11609
Tests
QA Steps
Same as the tests above
PR Author Checklist
### Fixed Issuessection aboveTestssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*filesWaiting for Copylabel for a copy review on the original GH to get the correct copy.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)Avataris modified, I verified thatAvataris working as expected in all cases)PR Reviewer Checklist
The reviewer will copy/paste it into a new comment and complete it after the author checklist is completed
### Fixed Issuessection aboveTestssectionQA stepssectiontoggleReportand notonIconClick).src/languages/*filesWaiting for Copylabel for a copy review on the original GH to get the correct copy.STYLE.md) were followedAvatar, I verified the components usingAvatarhave been tested & I retested again)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)Avataris modified, I verified thatAvataris working as expected in all cases)Web
Mobile Web - Chrome
Mobile Web - Safari
Desktop
iOS
Android