-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Improvements to Onyx.get
#2762
Comments
Triggered auto assignment to @mallenexpensify ( |
I think the answer to this is that, yes, we should. Can you briefly include the plan we will be moving forward with here for benchmarking? I think the plan is to create a single job to cover both so if we can add a bit more context in this issue that would be ideal. I think we should start with the benchmarks in one PR then move to the Onyx improvements. Lmk if that works for you @kidroca . |
Thanks @kidroca, I created the Upwork job, set the price at $2,000, made it private and invited you. Please continue all discussions here, @marcaaron will be assigned for feedback and PR review |
I've included it to the "Additional Work" section. Here is a bit more on that: Through decoration original source don't have to be modified and the benchmarking logic is maintained separately These modifications would allow the user of Onyx to display these metrics however they like
One simple example would be:
since
Yes, I'll open a draft PR and start with that |
Thanks @kidroca , I hired you in Upwork, I think you still need to accept. Assigning this issue to you now. |
Triggered auto assignment to @AndrewGable ( |
Prepared a little teaser with some before / after benchmark data Note that total time is the sum of all individual calls, but many happen in parallel. The total time is more of an indicator of CPU usage Device InfoPhysical Samsung Galaxy S7 edge BeforeScenario: Startup and loading the last viewed chat (with small chat)
Android.Before.mp4AfterScenario: Startup and loading the last viewed chat (with small chat)
Android.After.mp4 |
Woohoo!!
…On Tue, May 25, 2021 at 3:47 PM Peter Velkov ***@***.***> wrote:
Prepared a little teaser with some before / after benchmark data
Note that total time is the sum of all individual calls, but many happen
in parallel. The total time is more of an indicator of CPU usage
Device Info
Physical Samsung Galaxy S7 edge
Android 8.0
Before
Scenario: Startup and loading the last viewed chat (with small chat)
Method Total Max Min Average Calls
Onyx:get 9.1min 3.31sec 38.410ms 2.03sec 270
Onyx:getAllKeys 10.1min 3.29sec 57.505ms 2.00sec 304
Onyx:set 45.26sec 2.32sec 785.505ms 1.68sec 27
Onyx:merge 1.2min 5.45sec 0.010ms 2.23sec 32
Onyx:mergeCollection 10.67 3.94sec 3.28sec 3.56sec 3
https://user-images.githubusercontent.com/12156624/119576917-560e1280-bdc2-11eb-9a67-d47be70773f7.mp4
After
Scenario: Startup and loading the last viewed chat (with small chat)
Method Total Max Min Average Calls
Onyx:get 30.54sec 2.93sec 0.005ms 126.727ms 241
Onyx:getAllKeys 3.95sec 2.85sec 0.010ms 15.540ms 254
Onyx:set 23.63sec 1.42sec 458.880ms 945.169ms 25
Onyx:merge 32.31sec 3.41sec 11.255ms 1.35sec 24
Onyx:mergeCollection 3.69sec 1.42sec 1.04sec 1.23sec 3
https://user-images.githubusercontent.com/12156624/119577714-d3865280-bdc3-11eb-9658-ab39fd909aba.mp4
cc @quinthar <https://github.com/quinthar> @marcaaron
<https://github.com/marcaaron> @tgolen <https://github.com/tgolen>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2762 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEMNUSK6SHQ5RUP7F6FSRTTPQSIFANCNFSM44R6JR6A>
.
|
Wow, very awesome. In the "Before" table, the mergeCollection row, there is
a value of "10.67". What unit of time is that?
On Tue, May 25, 2021 at 4:50 PM David Barrett ***@***.***>
wrote:
… Woohoo!!
On Tue, May 25, 2021 at 3:47 PM Peter Velkov ***@***.***>
wrote:
> Prepared a little teaser with some before / after benchmark data
>
> Note that total time is the sum of all individual calls, but many happen
> in parallel. The total time is more of an indicator of CPU usage
> Device Info
>
> Physical Samsung Galaxy S7 edge
> Android 8.0
> Before
>
> Scenario: Startup and loading the last viewed chat (with small chat)
> Method Total Max Min Average Calls
> Onyx:get 9.1min 3.31sec 38.410ms 2.03sec 270
> Onyx:getAllKeys 10.1min 3.29sec 57.505ms 2.00sec 304
> Onyx:set 45.26sec 2.32sec 785.505ms 1.68sec 27
> Onyx:merge 1.2min 5.45sec 0.010ms 2.23sec 32
> Onyx:mergeCollection 10.67 3.94sec 3.28sec 3.56sec 3
>
>
>
https://user-images.githubusercontent.com/12156624/119576917-560e1280-bdc2-11eb-9a67-d47be70773f7.mp4
> After
>
> Scenario: Startup and loading the last viewed chat (with small chat)
> Method Total Max Min Average Calls
> Onyx:get 30.54sec 2.93sec 0.005ms 126.727ms 241
> Onyx:getAllKeys 3.95sec 2.85sec 0.010ms 15.540ms 254
> Onyx:set 23.63sec 1.42sec 458.880ms 945.169ms 25
> Onyx:merge 32.31sec 3.41sec 11.255ms 1.35sec 24
> Onyx:mergeCollection 3.69sec 1.42sec 1.04sec 1.23sec 3
>
>
>
https://user-images.githubusercontent.com/12156624/119577714-d3865280-bdc3-11eb-9658-ab39fd909aba.mp4
>
> cc @quinthar <https://github.com/quinthar> @marcaaron
> <https://github.com/marcaaron> @tgolen <https://github.com/tgolen>
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <
#2762 (comment)
>,
> or unsubscribe
> <
https://github.com/notifications/unsubscribe-auth/AAEMNUSK6SHQ5RUP7F6FSRTTPQSIFANCNFSM44R6JR6A
>
> .
>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2762 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAJMAB6POQMUMOBJO2XOB4DTPQSTBANCNFSM44R6JR6A>
.
|
@tgolen |
These numbers look fantastic. I think the hardest thing for me to wrap my mind around is the average |
Not on ios |
I could see how something like retrieving and parsing a very large chat could take this long. Most other things I'd expect to be very fast. |
I'd be interested to see the before/after for iOS too. I assume the numbers won't be drastic, but it would be nice to confirm that. |
Setup InfoiPhone 11 Pro Scenario: Startup and load last viewed chat (large chat 250 + messages) Before
After
Note: I've run the "After" tests first so any native cache benefits are in favor for the "Before" tests |
Thanks, that looks about like what I was expecting. This change is definitely going to get the averages down, but then we might want to start looking into some of those max values and see if we can do something about improving those specifically. |
What caught my eye is that a lot of the |
Nice observation. We ran into a similar problem with the
`session.authToken` because each IMG needs the authToken as part of
it's URL to display properly.
While the parent component idea would work, another alternative is what we
did with the authToken. We just made the Sessions.js file connect to Onyx
once and then export a `getAuthToken()` method that returned the single
Onyx value. Now, it looks like a lot of this implementation has been
removed (for whatever reason), but the idea is still sound.
I think I like the parent component idea better because there is no race
condition possibility (like if something called getAuthToken before the
authToken was set in Onyx).
…On Thu, May 27, 2021 at 5:18 PM Peter Velkov ***@***.***> wrote:
What caught my eye is that a lot of the get calls are for session and
personalData e.g. each chat comment seems to want them, but does it
really have to get it from Onyx. The data would be the same for each
comment. It would be more performant to have the parent component subscribe
for session and personalData and pass this down to the comments - 1
subscription vs +200 individual subscriptions -> +200 withOnyx instances
and the involved orchestration and memory
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2762 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAJMABZLJPF7FJIM56BTE2TTP3HM7ANCNFSM44R6JR6A>
.
|
I want to bring something up here so that it's clear This is does not mean that there is a problem, it's not like we'll be making copies - we're not A high level of how retrieving data from Onyx and cache works:
I hope you can see that even if direct reference is lost at some point:
Without cache: each read from disk retrieves a string value. A new object is then created from the string cc @quinthar @marcaaron @tgolen Edit: I'm just saying the above to address memory usage concerns - I still expect memory usage to decrease |
This PR is ready for a final review: Expensify/react-native-onyx#76 I'm not sure who to tag as a reviewer as per @marcaaron
|
I've been really heads-down in some highly urgent stuff, plus taking over some of Marc's tasks while he is out so I won't be able to review this PR at all (I've only been lightly following along). I think some good reviewers with be @AndrewGable @Jag96 and @Julesssss |
Can we post any updates regarding payment
cc @mallenexpensify (Tagging You as I see your name in the Upwork job) |
Thanks for the ping @kidroca it was my responsibility and I missed it (we previously didn't leave Contributor Managers assigned to issues, we now do). |
If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!
Problem:
withOnyx
.Solution:
This was widely discussed in the following places and it was decided to go with the cache solution:
Prevent unnecessary reads from disk
When a request is made to retrieve something from disk capture the task that would resolve with the read data, as more calls for the same key arrive, instead of making a separate call for the same thing redirect the reads to be resolved from the already pending task. This way only one round trip would ever happen for a given key. As soon as the data for the first call is available - all calls are resolved at once.
Cache and lazy loading
As data is read from file, keep a reference/pointer to the data in memory in a cache dictionary
Fill the cache lazily - only after a key was requested and read from file
Remove cache entries after the last connection for the given key is disconnected
Additional Work
✔️ Should we implement any benchmarks / metering?
The general principle I like to apply for a benchmark is through method decoration like the same here: Expensify/react-native-onyx#65 (comment)
cache
map since it should pretty much hold the same information - thought this is only possible after the update that adds cache...)ONYX_BENCHMARK
) to apply the metring function through decoration to a list of Onyx methodsget
,set
,merge
would pretty much work out of the boxreadCollectMetrics
andresetMetrics
as an Onyx methodget
with the a specifickey
Expected Result:
Onyx does not try to retrieve data that is already available in memory
Actual Result:
Onyx will always ask data from AsyncStorage
Action Performed:
N/A
Workaround:
Can the user still use Expensify without this being fixed? Have you informed them of the workaround?
Affected Platforms:
-[x] Web
-[x] iOS
-[x] Android
-[x] Desktop App
-[x] Mobile Web
Version Number:
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
View all open jobs on Upwork
The text was updated successfully, but these errors were encountered: