-
Notifications
You must be signed in to change notification settings - Fork 278
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
Virtual thread pinning using Conscrypt with Socket APIs #1170
Comments
Certainly sounds reasonable and we certainly use ReadWriteLocks for synchronisation elsewhere. My minor concern is that I don't have a feel for the performance of a ReentrantLock (or ReadWriteLock) plus try/finally versus That plus I don't think we have good benchmarks for this, and our existing benchmarks are rather bit-rotted. :/ |
I'm still trying to understand why the stack trace in the first comment is part of a deadlock, @carterkozak The lock in that case is the So I'm wondering if what you're seeing is actually a concurrency bug which gets exposed by thread pinning rather than a deadlock situation? Any chance you can get a full thread dump if it's reproducible for you? None of which invalidates the conversation about Reentrant or ReadWrite locks over Also, as I'm sure you're aware, there are no guarantees about read boundaries over |
Thanks for the replies, @prbprbprb. Using a ReentrantReadWriteLock sounds reasonable to me, I should have time to implement that change on Monday.
It's not a classic deadlock, but rather a loom carrier thread exhaustion deadlock: Without Conscrypt: With Conscrypt: This deadlock case is certainly a bit contrived (in practice it occurred within a JMH benchmark using a client and server in the same jvm). However, in cases that don't result in a deadlock, the inability to unmount and switch virtual threads on carriers has a substantial impact on application performance (I don't have the benchmark results available right now, but the difference was in the 10-20% range in synthetic testing between pinned virtual threads with an increased carrier pool size to avoid deadlocks, and virtual threads with this patch -- I haven't benchmarked to compare regular platform threads before/after this patch yet). |
I can put together a minimal reproducer of this case on Monday if it’s helpful |
Nah, your explanation makes total sense, thanks! As you say, it's somewhat contrived but Conscrypt should behave better under those circumstances. My main concern was that pinning was exposing some latent concurrency bug in Conscrypt, but it looks like it's "just" thread starvation due to suboptimal locking. |
Background
Conscrypt offers excellent performance, which is helpful now more than ever given the TLS performance regressions on x86_64 in JDK-18+. Unfortunately the Conscrypt Socket stream implementations synchronize over Socket I/O pinning virtual threads to carriers as described in jep-444. This prevents Conscrypt users from taking advantage of virtual threads (in fact introduces the deadlocks as all carriers become pinned).
Snippet from a unit test where enabling virtual threads resulted in a deadlock:
Proposed Solution
We should be able to retain existing behavior by replacing Object monitor locks with ReentrantLocks, which do not pin virtual threads. Such a change would need to be performance tested, and may impact observability (e.g. deadlock detection, thread dump metadata).
Does this seem reasonable? Would you accept such a contribution if I were to implement it?
Thanks!
The text was updated successfully, but these errors were encountered: