This is an automated email from the ASF dual-hosted git repository.
vpyatkov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new d89297b4d0 IGNITE-23707 Optimize update() in hybrid clocks (#4808)
d89297b4d0 is described below
commit d89297b4d072b5a023847b0e98a6d291d78518c3
Author: Vladislav Pyatkov <[email protected]>
AuthorDate: Fri Nov 29 14:58:33 2024 +0300
IGNITE-23707 Optimize update() in hybrid clocks (#4808)
---
.../ignite/internal/hlc/HybridClockImpl.java | 25 ++++++++++------
.../ignite/internal/hlc/HybridClockTest.java | 6 ++--
.../hlc/benchmarks/HybridClockBenchmark.java | 33 ++++++++++++++++++++--
.../ignite/internal/tx/impl/HeapLockManager.java | 5 ++--
4 files changed, 53 insertions(+), 16 deletions(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridClockImpl.java
b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridClockImpl.java
index 4960824454..6ff8948ff1 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridClockImpl.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridClockImpl.java
@@ -111,20 +111,29 @@ public class HybridClockImpl implements HybridClock {
*/
@Override
public final HybridTimestamp update(HybridTimestamp requestTime) {
+ long requestTimeLong = requestTime.longValue();
+
while (true) {
- long now = currentTime();
+ long oldLatestTime = this.latestTime;
- // Read the latest time after accessing UTC time to reduce
contention.
- long oldLatestTime = latestTime;
+ if (oldLatestTime >= requestTimeLong) {
+ return hybridTimestamp(LATEST_TIME.incrementAndGet(this));
+ }
- long newLatestTime = max(requestTime.longValue() + 1, max(now,
oldLatestTime + 1));
+ long now = currentTime();
- // TODO https://issues.apache.org/jira/browse/IGNITE-23707 avoid
CAS on logical part update.
+ if (now > requestTimeLong) {
+ if (LATEST_TIME.compareAndSet(this, oldLatestTime, now)) {
+ return hybridTimestamp(now);
+ }
+ } else {
+ long newLatestTime = requestTimeLong + 1;
- if (LATEST_TIME.compareAndSet(this, oldLatestTime, newLatestTime))
{
- notifyUpdateListeners(newLatestTime);
+ if (LATEST_TIME.compareAndSet(this, oldLatestTime,
newLatestTime)) {
+ notifyUpdateListeners(newLatestTime);
- return hybridTimestamp(newLatestTime);
+ return hybridTimestamp(newLatestTime);
+ }
}
}
}
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridClockTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridClockTest.java
index f7d3b68e3a..3b141488d9 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridClockTest.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridClockTest.java
@@ -75,13 +75,13 @@ class HybridClockTest extends BaseIgniteAbstractTest {
assertTimestampEquals(100, new HybridTimestamp(100, 2),
() -> clock.update(new HybridTimestamp(60, 1000)));
- assertTimestampEquals(200, new HybridTimestamp(200, 0),
+ assertTimestampEquals(200, new HybridTimestamp(100, 3),
() -> clock.update(new HybridTimestamp(70, 1)));
- assertTimestampEquals(50, new HybridTimestamp(200, 1),
+ assertTimestampEquals(50, new HybridTimestamp(100, 4),
() -> clock.update(new HybridTimestamp(70, 1)));
- assertTimestampEquals(500, new HybridTimestamp(500, 0),
+ assertTimestampEquals(500, new HybridTimestamp(100, 5),
() -> clock.update(new HybridTimestamp(70, 1)));
assertTimestampEquals(500, new HybridTimestamp(600, 1),
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/hlc/benchmarks/HybridClockBenchmark.java
b/modules/core/src/test/java/org/apache/ignite/internal/hlc/benchmarks/HybridClockBenchmark.java
index f821e5cbb2..f83e6bf713 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/hlc/benchmarks/HybridClockBenchmark.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/hlc/benchmarks/HybridClockBenchmark.java
@@ -17,9 +17,12 @@
package org.apache.ignite.internal.hlc.benchmarks;
+import static
org.apache.ignite.internal.hlc.HybridTimestamp.LOGICAL_TIME_BITS_SIZE;
+
import java.util.concurrent.TimeUnit;
import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.hlc.HybridClockImpl;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
@@ -43,8 +46,8 @@ import org.openjdk.jmh.runner.options.OptionsBuilder;
@Fork(1)
@Warmup(iterations = 5, time = 2)
@Measurement(iterations = 10, time = 2)
-@BenchmarkMode(Mode.AverageTime)
-@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
public class HybridClockBenchmark {
/** Clock to benchmark. */
private HybridClock clock;
@@ -75,12 +78,38 @@ public class HybridClockBenchmark {
hybridClockNow();
}
+ @Benchmark
+ @Threads(1)
+ public void hybridClockUpdateSingleThread() {
+ hybridClockUpdate();
+ }
+
+ @Benchmark
+ @Threads(5)
+ public void hybridClockUpdateFiveThreads() {
+ hybridClockUpdate();
+ }
+
+ @Benchmark
+ @Threads(10)
+ public void hybridClockUpdateTenThreads() {
+ hybridClockUpdate();
+ }
+
private void hybridClockNow() {
for (int i = 0; i < 1000; i++) {
clock.now();
}
}
+ private void hybridClockUpdate() {
+ for (int i = 0; i < 1000; i++) {
+ long ts = ((System.currentTimeMillis() + (i % 2 == 0 ? 5 : -5)) <<
LOGICAL_TIME_BITS_SIZE) + (i % 10);
+
+ clock.update(HybridTimestamp.hybridTimestamp(ts));
+ }
+ }
+
/**
* Benchmark's entry point.
*/
diff --git
a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/HeapLockManager.java
b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/HeapLockManager.java
index deaac3d07f..732d71609a 100644
---
a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/HeapLockManager.java
+++
b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/HeapLockManager.java
@@ -174,7 +174,7 @@ public class HeapLockManager extends
AbstractEventProducer<LockEvent, LockEventP
if (lockKey.contextId() == null) { // Treat this lock as a
hierarchy(coarse) lock.
CoarseLockState state = coarseMap.computeIfAbsent(lockKey, key ->
new CoarseLockState(lockKey));
- return state.acquire(txId, lockKey, lockMode);
+ return state.acquire(txId, lockMode);
}
while (true) {
@@ -521,11 +521,10 @@ public class HeapLockManager extends
AbstractEventProducer<LockEvent, LockEventP
* Acquires a lock.
*
* @param txId Tx id.
- * @param lockKey Lock key.
* @param lockMode Lock mode.
* @return The future.
*/
- public CompletableFuture<Lock> acquire(UUID txId, LockKey lockKey,
LockMode lockMode) {
+ public CompletableFuture<Lock> acquire(UUID txId, LockMode lockMode) {
switch (lockMode) {
case S:
stripedLock.writeLock().lock();