Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.52k stars 2.87k forks source link

[HOLD for payment 2024-09-23] Performance Improvement: Update formatjs libraries and upstream/patch date-fns-tz #47988

Closed hurali97 closed 1 month ago

hurali97 commented 2 months ago

Problem

While we were analysing the latest traces from Jason, we realised that there's substantial amount of time spent in formatjs and date-fns-tz. We also double-checked this with our heavy accounts (~15k reports) and we got the same results. Following is how things look like on baseline:

Baseline

Screenshot 2024-08-26 at 12 47 42 PM

snapshot from profile ![Screenshot 2024-08-26 at 12 41 31 PM](https://github.com/user-attachments/assets/023f56f3-ce11-4c83-88d9-93d07ffaf82d)

Solution:

While analysing the traces, we curated a list of places that can be improved in formatjs and date-fns-tz. Two noticeable items are BestFitMatcher from formatjs and getDateTimeFormat from date-fns-tz. Now, since these are third party libraries, we can bump them to the latest versions and see if they are already fixing performance related issues. We compared the code for BestFitMatcher from the currently installed version formatjs/intl-locale@3.3.0 with formatjs/intl-locale@4.0.0 and there was a significant refactor of this file.

So it only made sense to bump formatjs libraries to the latest to get the performance improvements out of the box. For date-fns-tz there was no significant updates to getDateTimeFormat function, so to apply the improvements we have two options:

However, we don't know how long it would take for option 2 as it depends on the reviewer of that repo. We can maybe move forward by mixing both options and removing the patch, once our PR is merged and available on NPM.

The improvement for getDateTImeFormat is pretty simple. We have Intl.DateTimeFormat being re-initialised every time getDateTimeFormat is invoked. Since testDateFormatted is a static variable, we can move it outside of the function.

var dtfCache = {};

// Moved this out from `getDateTimeFormat`
    var testDateFormatted = new Intl.DateTimeFormat('en-US', {
      hour12: false,
      timeZone: 'America/New_York',
      year: 'numeric',
      month: 'numeric',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit'
    }).format(new Date('2014-06-25T04:00:00.123Z'));
    var hourCycleSupported = testDateFormatted === '06/25/2014, 00:00:00' || testDateFormatted === '‎06‎/‎25‎/‎2014‎ ‎00‎:‎00‎:‎00';

function getDateTimeFormat(timeZone) {
 ...someImplementation
  return dtfCache[timeZone];
}

Below is how things look like after formatjs version bumps and date-fns-tz patch:

Screenshot 2024-08-26 at 1 03 06 PM

snapshot from profile ![Screenshot 2024-08-26 at 12 42 15 PM](https://github.com/user-attachments/assets/83ce706f-1bcd-473b-bc33-b10fb1833772)

To summarise;


melvin-bot[bot] commented 2 months ago

📣 @seeronline! 📣 Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Make sure you've read and understood the contributing guidelines.
  2. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  3. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  4. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details. Screen Shot 2022-11-16 at 4 42 54 PM Format:
    Contributor details
    Your Expensify account email: <REPLACE EMAIL HERE>
    Upwork Profile Link: <REPLACE LINK HERE>
flyinghead commented 2 months ago

seeronline's link contains a malicious file. Don't download: https://www.virustotal.com/gui/file/b127de888f09ce23937c12b7fccfa47a8f48312b0e43eb59b6243f665c6d366a

melvin-bot[bot] commented 2 months ago

📣 @flyinghead! 📣 Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Make sure you've read and understood the contributing guidelines.
  2. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  3. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  4. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details. Screen Shot 2022-11-16 at 4 42 54 PM Format:
    Contributor details
    Your Expensify account email: <REPLACE EMAIL HERE>
    Upwork Profile Link: <REPLACE LINK HERE>
melvin-bot[bot] commented 2 months ago

Current assignee @mountiny is eligible for the AutoAssignerNewDotQuality assigner, not assigning anyone new.

melvin-bot[bot] commented 2 months ago

Triggered auto assignment to @strepanier03 (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

roryabraham commented 2 months ago

we can maybe move forward by mixing both options and removing the patch, once our PR is merged and available on NPM

This is generally my preferred approach. Report the issue with a minimal reproduction, and create a PR to fix it upstream. If you don't receive any feedback, proceed with a patch and create an issue to eventually remove the patch once the upstream fix is merged. If you do get feedback and the maintainer doesn't want to merge your fix for some reason, re-evaluate and open up a conversation with the team.

roryabraham commented 2 months ago

looks like some good finds @hurali97 👍🏼

hurali97 commented 2 months ago

PR for date-fns-tz library is here. Now, we can wait for two days and if there's no update from the reviewer, we will go ahead with creating the patch in Expensify.

roryabraham commented 2 months ago

sounds great 👍🏼

Ollyws commented 1 month ago

Could someone process payment for my review of https://github.com/Expensify/App/pull/48067, thanks!

mountiny commented 1 month ago

@Ollyws sorry, the automation failed here.

$250 to @Ollyws for their review, no regression tests required for this task cc @strepanier03

mountiny commented 1 month ago

Noting we do not want to close this but make it monthly so we can track of the upstream PR

Ollyws commented 1 month ago

Requested in ND.

melvin-bot[bot] commented 1 month ago

Skipping the payment summary for this issue since all the assignees are employees or vendors. If this is incorrect, please manually add the payment summary SO.

garrettmknight commented 1 month ago

$250 approved for @Ollyws

mountiny commented 1 month ago

I think we can close now then