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

fix(form): optimize calculated question performance #2339

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

czosel
Copy link
Contributor

@czosel czosel commented Dec 2, 2024

  • drop several signals in favor of explicit calls in domain logic to allow reuse of form structure
  • add prefetching for document structure
  • apply topological sorting before calculating answers on document creation

@luytena
Copy link
Contributor

luytena commented Dec 10, 2024

@czosel Note: Instance creation is still slow, and seems to be triggered by create in SaveDocumentLogic. I'm having a look.

@luytena
Copy link
Contributor

luytena commented Dec 10, 2024

Form changes (e.g. through form-builder) are probably also still slow.

@czosel czosel force-pushed the fix-calculated-question-performance branch 4 times, most recently from a47c6e1 to 33746a0 Compare December 31, 2024 08:18
@czosel czosel changed the title fix(form): optimize calculated question performance (wip) fix(form): optimize calculated question performance Dec 31, 2024
@czosel czosel force-pushed the fix-calculated-question-performance branch 2 times, most recently from 4584728 to d1bd793 Compare December 31, 2024 08:27
Comment on lines -104 to -122
@receiver(post_save, sender=models.Question)
@disable_raw
@filter_events(lambda instance: instance.type == models.Question.TYPE_CALCULATED_FLOAT)
def update_calc_from_question(sender, instance, created, update_fields, **kwargs):
# TODO optimize: only update answers if calc_expression is updated
# needs to happen during save() or __init__()

for document in models.Document.objects.filter(form__questions=instance):
update_or_create_calc_answer(instance, document)


@receiver(post_save, sender=models.FormQuestion)
@disable_raw
@filter_events(
lambda instance: instance.question.type == models.Question.TYPE_CALCULATED_FLOAT
)
def update_calc_from_form_question(sender, instance, created, **kwargs):
for document in instance.form.documents.all():
update_or_create_calc_answer(instance.question, document)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I dropped these two handlers completely. On my local instance, updating a calculated question took about 10s, even though I only had 10 documents in the DB. Since in typical prod scenarios we have thousands of documents, this kind of thing should be done, if needed, explicitly in a management command.

@czosel czosel force-pushed the fix-calculated-question-performance branch from d1bd793 to ad4d2e7 Compare December 31, 2024 08:34
calc_question.calc_expression = "'sub_question'|answer -1"
calc_question.save()
calc_ans.refresh_from_db()
assert calc_ans.value == 99
Copy link
Contributor Author

@czosel czosel Dec 31, 2024

Choose a reason for hiding this comment

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

This functionality was dropped: When updating the calc expression of a calculated question, the answers are not updated automatically anymore.

@czosel czosel marked this pull request as ready for review December 31, 2024 08:38
@czosel czosel force-pushed the fix-calculated-question-performance branch from ad4d2e7 to 55cf7ec Compare December 31, 2024 09:47
@czosel czosel force-pushed the fix-calculated-question-performance branch from 0426441 to af7e014 Compare December 31, 2024 11:08
@czosel czosel requested a review from winged December 31, 2024 12:01
],
)
) # fmt:skip
Copy link
Contributor Author

Choose a reason for hiding this comment

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

drive-by fix: exclude this block from autoformatting so that all parametrizations can stay one one line

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.

2 participants