-
Notifications
You must be signed in to change notification settings - Fork 25k
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
Do not lock on reads of XPackLicenseState #52437
Conversation
XPackLicenseState reads to necessary to validate a number of cluster operations. This reads occasionally occur on transport threads which should not be blocked. Currently we sychronize when reading. However, this is unecessary as only a single piece of state is updateable. This commit makes this state volatile and removes the locking.
Pinging @elastic/es-security (:Security/License) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a question.
x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java
Show resolved
Hide resolved
I would like to understand whether this has been an issue in practice? Read write locks can be slow and much slower than synchronized depending on the workload. StampedLock with optimistic concurrency might be a better choice but more complex |
Anyway, I am fine with whatever approach that avoids blocking on reads. Read write locks seem fine to me, since the write will almost never happens. Volatile read seems fine to me as it is definitely the most performant, but I understand @jasontedor concern that it may not be immediately obvious to many developers that you need to copy locally before reading multiple times. StampedLock seems not ideal to me because we are only saving some overhead vs. read write lock. And it does not seem simpler than volatile read approach which is where we should go if we are concerned about acquire op performance. |
This is true, but I wouldn’t expect this to be one since writes are exceptionally rare. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
I ran a JMH benchmark for this. With N threads reading a value concurrently for a ReadWriteLock, StampedLock using optimistic concurrency, synchronized variable access, and volatile reads. On my laptop with 10 warmup iterations and 10 iterations: 2 threads:
4 threads:
10 threads:
20 threads:
Given this, I do not see how this change will improve the performance of indexing. |
One way to implement StampedLock could look something like: private final StampedLock stampedLock = new StampedLock();
private final ReleasableLock readLock = new ReleasableLock(stampedLock.asReadLock());
public boolean checkOptimistically(Predicate<Status> statusPredicate) {
final long stamp = stampedLock.tryOptimisticRead();
final boolean status = statusPredicate.test(counter);
if (rwlock.validate(stamp) == false) {
try (ReleasableLock lock = readLock.acquire()) {
return statusPredicate.test(state);
}
}
return status;
} Each method could call that method with a predicate to test the status object. |
I had not seen that the |
You do not have to, but not doing so degrades performance to the level of a ReentrantReadWriteLock. I think if we're trying to avoid blocking transport threads volatile would be the best choice with a pattern such as:
This along with comments about needing to use the same status in the check should be enough or at least I think. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks for the iterations. Thanks @jaymode for the convincing benchmarks that got us here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for letting me chime in
XPackLicenseState reads to necessary to validate a number of cluster operations. This reads occasionally occur on transport threads which should not be blocked. Currently we sychronize when reading. However, this is unecessary as only a single piece of state is updateable. This commit makes this state volatile and removes the locking.
XPackLicenseState reads to necessary to validate a number of cluster operations. This reads occasionally occur on transport threads which should not be blocked. Currently we sychronize when reading. However, this is unecessary as only a single piece of state is updateable. This commit makes this state volatile and removes the locking.
XPackLicenseState reads to necessary to validate a number of cluster
operations. This reads occasionally occur on transport threads which
should not be blocked. Currently we sychronize when reading. However,
this is unecessary as only a single piece of state is updateable. This
commit makes this state volatile and removes the locking.