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

PERF: Speed up PostSerializer#reactions by avoiding nested loop take 2 #313

Merged
merged 1 commit into from
Oct 11, 2024

Conversation

tgxworld
Copy link
Contributor

This is a follow-up to 7467349.

Within the object.post_actions.reject loop, we are running through
another loop given by object.post_actions_with_reaction_users&.find.
When the object.post_actions and
object.post_actions_with_reaction_users array is large, we end up
spending alot of time executing the loops.

This commit resolves the problem by reducing the number of records we
loop in object.post_actions_with_reaction_users by prefiltering the
records by post_action.id to remove alot of unnecessary iterations in
the loop.

Local benchmarks for the method for 8000 items in object.post_actions records and 2000
items in post_actions_with_reaction_users shows the runtime of the
method decreasing from roughly 7seconds to about 5ms.

@@ -29,8 +35,7 @@ def posts
)

posts.each do |post|
post.post_actions_with_reaction_users =
post_actions_with_reaction_users.select { |post_action| post_action.post_id == post.id }
Copy link
Contributor Author

@tgxworld tgxworld Oct 11, 2024

Choose a reason for hiding this comment

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

This was looping through the whole array once per post which is inefficient. Instead, we reduce the array into a hash keyed by the post_action.post_id instead so that we can just do a O(1) hash lookup when setting post.post_actions_with_reaction_users.

This is a follow-up to 7467349.

Within the `object.post_actions.reject` loop, we are running through
another loop given by `object.post_actions_with_reaction_users&.find`.
When the `object.post_actions` and
`object.post_actions_with_reaction_users` array is large, we end up
spending alot of time executing the loops.

This commit resolves the problem by reducing the number of records we
loop in `object.post_actions_with_reaction_users` by prefiltering the
records by `post_action.id` to remove alot of unnecessary iterations in
the loop.

Local benchmarks for the method for 8000 items in `object.post_actions` records and 2000
items in `post_actions_with_reaction_users` shows the runtime of the
method decreasing from roughly 7seconds to about 5ms.
Comment on lines +115 to +118
object.post_actions_with_reaction_users[post_action.id]
&.reaction_user
&.reaction
&.reaction_value == DiscourseReactions::Reaction.main_reaction_id
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No more nested loop here and we can just do a O(1) hash lookup.

@tgxworld tgxworld merged commit 708722a into main Oct 11, 2024
5 checks passed
@tgxworld tgxworld deleted the perf_improvement branch October 11, 2024 02:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants