Skip to content

[Hold for payment 2021-08-17] [Performance] Optimize AsyncStorage on Android #2667

@arielgreen

Description

@arielgreen

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

Though not carefully benchmarked, it's pretty obvious that the Android app is slow -- to start, to use, etc. And all things being equal, it would be better if it were faster. We don't know exactly what fraction of that time is spent reading/writing data from/to disk, but it's nonzero, and if it were faster, it would be a rising tide that floats all boats.

Solution

Do the following:

  1. Create a standalone RN app that benchmarks AsyncStorage. I think it should have three buttons, each of which outputs timing information to a log:
    a. Reset - Deletes the database on disk
    b. Write Sequential - Inserts a random number into keys 0 to 1M sequentially
    c. Read Sequential - (only active if there is a database) Read rows 0 to 1M sequentially
  2. Do some basic tests on both Android and iOS, and record timing from these scenarios in order:
    a. Cold write sequential - Reset the database, reboot the phone, then start the app and tap "Write Sequential". This will measure the ability to write to a "cold" disk that has nothing cached.
    b. Warm write - After doing "Cold write", tap "Write Sequential" again and see how overwriting the same database (presumably that is already cached) differs in performance.
    c. Warm read - After "Warm write", tap "Read Sequential" and see how reading a warmed-up file performs.
    d. Cold read - Reboot the phone, open the app, then tap "Read Sequential" again, to see how read performance differs when the file isn't cached
  3. Refactor AsyncStorage on Android to implement each of the suggested optimizations described here, and re-run the benchmark after each to see which helps and by how much, namely:
    a. Stored procedures (to avoid recompiling SQL every time)
    b. PRAGMA synchronous=OFF;
    c. PRAGMA mmap_size=(1010241024); // 10MB memory map
    d. Update the "Sequential Read" test to read keys in batches of 100, and re-test with the stock implementation (which just calls AsyncStorage.get() multiple times). Then implement a native version of AsyncStorage.multiGet() that makes a single query to SQLite, and re-test.
  4. Once we've found the winning combo (if any), submit to the React Native mainline to see if we can get them to merge it. However, you'll get paid whether or not they do.

Also, test a native version of AsyncStorage.mutliGet() that does it all in one query.

Upwork job post

View all open jobs on Upwork

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions