Skip to content

Conversation

@obourgain
Copy link

Fair locks are fair, which mean,s that they are locked in the order threads called lock() and not in pseudo random order, but they are slow. Like very slow.

Invoking The Random Guy On The Internet Who Did Some Benchmarks, we can see that fair locks are like a hundred time slower blog here.

We had a production issue with a lot of threads waiting to lock these locks.

To go a bit deeper, the semantic of what is done under those locks looks a lot like a Map.computeIfAbsent(), and the code could gain clarity and probably performance by using a ConcurrentHashMap. As the attribute names are a char[] with offset and length and not a String, there would need to be a smart wrapper for the key. That means an light object allocation for each access, I don't think that's a big deal.

Another alternative would be to keep the pair of Lists, but instead of a big lock around both, we could store them in a AtomicReference (to be precise: one AtomicRef storing some ligh object containing the two Lists). On access, the methods would load the two lists without the lock and when update is needed, they could update the Lists optimistically, try to swap the AtomicRef's content, and retry the whole update cycle on failure.

WDYT?

Fair locks are fair, which mean,s that they are locked in the order
threads called lock() and not in pseudo random order, but they are slow.
Like very slow.

Invoking The Random Guy On The Internet Who Did Some Benchmarks, we can
see that fair locks are like a hundred time slower [blog here](https://alidg.me/blog/2020/3/7/scalable-fair-lock#barging--fairness-cost).

We had a production issue with a lot of threads waiting to lock these
locks.

To go a bit deeper, the semantic of what is done under those locks looks
a lot like a Map.computeIfAbsent(), and the code could gain clarity and
probably performance by using a ConcurrentHashMap. As the attribute
names are a char[] with offset and length and not a String, there would need to be a smart wrapper for the key.
That means an light object allocation for each access, I don't think that's a big
deal.

Another alternative would be to keep the pair of Lists, but instead of a
big lock around both, we could store them in a AtomicReference (to be
precise: one AtomicRef storing some ligh object containing the two
Lists). On access, the methods would load the two lists without the lock and when update is needed,
they could update the Lists optimistically, try to swap the AtomicRef's
content, and retry the whole update cycle on failure.

WDYT?
@obourgain
Copy link
Author

any feedback?

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.

1 participant