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

Improve performance with very large numbers of notifiers #7424

Merged
merged 2 commits into from
Mar 7, 2024

Conversation

tgoyne
Copy link
Member

@tgoyne tgoyne commented Mar 6, 2024

With large notifier counts the lock contention on CollectionNotifier::m_realm becomes a very significant overhead, with unlock() taking upwards of 50% of the total runtime. This is only a problem when the notifiers run on the background thread and the target thread forces a refresh, as there's otherwise no contention. Using an atomic variable to avoid the mutex solves the problem entirely.

std::unordered_map is pretty slow and TableKeys are almost dense so we can use a vector instead. This speeds up almost-noop notifications where gathering the related table information is the bulk of the runtime in obj-c by~20%.

Together these speed up one of the obj-c benchmarks from 2.959 seconds to .765 seconds. The newly added object-store benchmark is less dramatic but still goes from 86ms to 46ms.

std::unordered_map is pretty slow and TableKeys are *almost* dense so we can
use a vector instead. This speeds up almost--noop notifications in obj-c by
~20%.
@tgoyne tgoyne self-assigned this Mar 6, 2024
@cla-bot cla-bot bot added the cla: yes label Mar 6, 2024
With large notifier counts the lock contention on CollectionNotifier::m_realm
becomes a very significant overhead, with unlock() taking upwards of 50% of the
total runtime. This is only a problem when the notifiers run on the background
thread and the target thread forces a refresh, as there's otherwise no
contention. Using an atomic variable to avoid the mutex solves the problem
entirely.
@tgoyne tgoyne force-pushed the tg/notifier-perf branch from bde02e0 to ac03946 Compare March 6, 2024 19:15
@tgoyne tgoyne requested a review from ironage March 6, 2024 20:13
std::vector<LinkInfo> complete_mapping;
complete_mapping.resize(group->size());
auto get_mapping = [&](TableKey key) -> LinkInfo& {
size_t ndx = Group::key2ndx(key);
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like table keys will be recycled after 100 table removals. I think that would lead to an already initialized LinkInfo being returned from here. Even if not, it seems like a risk that we are using implementation details of a TableKey (though we have done worse in the name of performance). Could we get similar performance improvement by using our util::FlatMap?

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 is a temporary data structure that doesn't outlive this function, and the state of the transaction it's reading from can't change while it exists.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, you're right. All good then, thanks! 👍

@tgoyne tgoyne merged commit eab7f1d into master Mar 7, 2024
37 checks passed
@tgoyne tgoyne deleted the tg/notifier-perf branch March 7, 2024 17:28
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants