-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Optimize entity form load times #6318
Conversation
I'm able to run this on my Galaxy A13 by rebasing on #6353 and making the following change to
I thought about doing a PR for this but it doesn't seem to happen even on the A13 unless I'm launching from Android Studio so maybe it doesn't need to be addressed. I asked about the pref on Stackoverflow and CommonsWare said it could be related to I printed out the actual time for each benchmark: That means the current assertions won't pass with the target device. I think we can merge this and then follow up with targeted improvements? Or make those here, I don't have a strong preference! |
import org.odk.collect.strings.R | ||
|
||
/** | ||
* Benchmarks the performance of entity follow up forms. [PROJECT_URL] should be set to a project |
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.
Wouldn't it be better to have a demo server for such test forms so that we don't have to configure anything?
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.
Great point! I think we're potentially planning that for a beta as well. Let's leave this as-is for the moment, but I like the idea of that being how it works later.
|
||
.clickOK(MainMenuPage()) | ||
.clickGetBlankForm() | ||
.benchmark("Updating form with http cache", stopwatch) { |
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.
If it's the same form without any updates it's not really updating, right? Downloading will be skipped so what takes time here is comparing the differences. Am I right?
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.
Yeah, it should really be "Checking for updates when there are none" or something. I'll rename.
assertThat(stopwatch.getTime("Updating form with http cache"), lessThan(90)) | ||
assertThat(stopwatch.getTime("Loading form first time"), lessThan(5)) | ||
assertThat(stopwatch.getTime("Loading form second time"), lessThan(5)) | ||
assertThat(stopwatch.getTime("Filtering select"), lessThan(5)) |
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.
I think you can add const for those keys as they are used here and above.
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.
I've changed the way we benchmark/assert so that they only need to be referenced once instead.
collect_app/src/androidTest/java/org/odk/collect/android/benchmark/EntitiesBenchmarkTest.kt
Outdated
Show resolved
Hide resolved
Yeah, let's follow up as this PR is blocking other changes. |
Tested with Success! Verified on device with Android 14, 10 Verified cases:
|
Blocked by #6290Load times should now be under 5s on most devices.
I've also added a new
EntitiesBenchmarkTest
that can be run manually against different real devices. This will let us check that we don't regress performance around entity forms.Why is this the best possible solution? Were any other approaches considered?
I did some profiling on bottlenecks for form load time, and it appeared the most significant was the cost involved in performing
DatabaseEntitiesRepository#getEntities
. Digging in further, it appears this was due to the time it takes to construct aList
containing all the entities (in a list) from theCursor
query as it has to move through many items and for large lists this results in filling the cursor window multiple times.To alleviate that bottleneck, I've introduced
getCount
andgetByIndex
methods that can be used when loading a form (where we just do a "partial" parse) instead of needing to load all the entities.How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?
This should just affect entity forms. Entity forms that have a select containing every entity on the first screen will not be any faster as this still requires the app to load all entities for a list.
Before submitting this PR, please make sure you have:
./gradlew connectedAndroidTest
(or./gradlew testLab
) and confirmed all checks still passDateFormatsTest