Skip to content
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

Cache and reuse dynamic choice lists #619

Merged
merged 16 commits into from
Mar 22, 2021

Conversation

lognaturel
Copy link
Member

@lognaturel lognaturel commented Jan 29, 2021

Speeds up displaying previously-filtered choice lists.
Closes getodk/collect#4363

What has been done to verify that this works as intended?

Added and ran tests, tried it in Collect.

Why is this the best possible solution? Were any other approaches considered?

We've talked about many possible performance improvements in this area. Most would only work in some cases. Adding caching works for any choice filter expression and gives us O(1) performance in many cases. Initially computing a choice list is O(N) and can still be slow but once it's computed, we don't have to do it again. I think this is a relatively low-risk, high impact change that we want to do no matter what other improvements we make later.

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?

The intent is just to speed up displaying filtered choice lists that were previously filtered and didn't change. There's risk around all things dynamic choice lists.

I initially thought that this would increase memory usage but I believe that it makes no difference because a choice list was always saved in ItemsetBinding previously, it just was immediately discarded.

Do we need any specific form for testing your changes? If so, please attach one.

See tests.

Does this change require updates to documentation? If so, please file an issue here and include the link below.

No.

@lognaturel lognaturel marked this pull request as draft January 29, 2021 22:08
@lognaturel lognaturel force-pushed the cache-choices branch 4 times, most recently from c544a2b to 2016964 Compare February 2, 2021 05:44
@codecov-io
Copy link

codecov-io commented Feb 2, 2021

Codecov Report

Merging #619 (f361264) into master (fcdaed0) will increase coverage by 0.00%.
The diff coverage is 61.29%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #619   +/-   ##
=========================================
  Coverage     55.19%   55.19%           
- Complexity     3261     3269    +8     
=========================================
  Files           246      246           
  Lines         13396    13388    -8     
  Branches       2573     2572    -1     
=========================================
- Hits           7394     7390    -4     
- Misses         5198     5201    +3     
+ Partials        804      797    -7     
Impacted Files Coverage Δ Complexity Δ
...in/java/org/javarosa/form/api/FormEntryPrompt.java 20.89% <8.10%> (-11.56%) 16.00 <1.00> (-4.00)
src/main/java/org/javarosa/core/model/FormDef.java 71.02% <66.66%> (-0.65%) 148.00 <0.00> (-15.00)
...n/java/org/javarosa/core/model/ItemsetBinding.java 79.41% <84.52%> (+5.12%) 45.00 <37.00> (+23.00)
.../java/org/javarosa/core/model/utils/DateUtils.java 58.98% <0.00%> (-0.29%) 76.00% <0.00%> (-2.00%)
...rg/javarosa/core/model/instance/TreeReference.java 74.73% <0.00%> (ø) 114.00% <0.00%> (+2.00%)
...a/org/javarosa/xform/parse/FormInstanceParser.java 72.61% <0.00%> (+0.92%) 110.00% <0.00%> (+2.00%)
...ain/java/org/javarosa/core/model/SelectChoice.java 83.72% <0.00%> (+2.32%) 20.00% <0.00%> (+1.00%)
...org/javarosa/core/model/instance/DataInstance.java 52.29% <0.00%> (+2.75%) 25.00% <0.00%> (+1.00%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update fcdaed0...f361264. Read the comment docs.

FormEntryPrompts are used ephemerally so in practice this generally has no effect. It's a weird division of responsibility, anyway.
This gives ItemsetBinding the responsibility of figuring out whether its cached list is valid or needs to be recomputed so client code doesn't need to know about that process.
The contextualized trigger references will be different for different repeat instances so the current question is accounted for in that way.
@lognaturel lognaturel marked this pull request as ready for review February 17, 2021 20:52
@lognaturel
Copy link
Member Author

I ran DynamicSelectUpdateTest, SelectOneChoiceFilterTest, SelectMultipleChoiceFilterTest and XPathFuncExprRandomizeTest with coverage and am happy with the line coverage (with the understanding that doesn't mean all concepts are covered). The lines that lack coverage are:

  • error handling for unlikely corner cases
  • related to "copy mode" which I know nothing about and did my best to just not touch
  • have TODO comments because I suspect the code does nothing at all

I think the last thing pending is for @dcbriccetti to flag areas he's not confident about so we can compare notes and see whether there are additional areas of risk I might have missed.

So that forms make sense when rendered by a client and filled by hand. This makes no difference for the tests.
Copy link
Contributor

@dcbriccetti dcbriccetti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks for addressing all my concerns.

@lognaturel
Copy link
Member Author

Thanks so much for all the great feedback and checks!

@lognaturel lognaturel merged commit 18391aa into getodk:master Mar 22, 2021
@lognaturel lognaturel deleted the cache-choices branch March 22, 2021 22:19
@@ -318,7 +292,8 @@ public String getHelpText() {


/**
* Attempts to return the specified Item (from a select or 1select) text.
* Attempts to return the specified item text from a STATIC select or select1. Does NOT
* support dynamic selects ({@see ItemsetBinding}).
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment suggests I thought this was not applicable to dynamic selects. However, it's now crashing for dynamic selects so something is not right: #625 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. There's Collect code that directly calls getSelectItemText regardless of whether the select is static or dynamic. It seems that used to work and doesn't anymore.

//will no longer be an option this go around
if(choice != null)
{
selection.add(choice.selection());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this used to ensure there was always a SelectionChoice for the Selection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

When going to a screen with a dynamic choice list, the choice list is computed twice
3 participants