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();

Reply via email to