This is an automated email from the ASF dual-hosted git repository.

mck pushed a commit to branch cassandra-3.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/cassandra-3.0 by this push:
     new 5a6d52b  Remove CAS failures and competition in Region.allocate(..) 
methods with use of getAndAdd(..) updates instead of compareAndSet(..) loops.
5a6d52b is described below

commit 5a6d52b26191ab1f5df6e9cf941e0f964dd95a28
Author: Mick Semb Wever <m...@apache.org>
AuthorDate: Sun Jul 5 14:06:25 2020 +0200

    Remove CAS failures and competition in Region.allocate(..) methods with use 
of getAndAdd(..) updates instead of compareAndSet(..) loops.
    
     patch by Mick Semb Wever; reviewed by Robert Stupp, Benedict Elliott Smith 
for CASSANDRA-15922
---
 CHANGES.txt                                        |  1 +
 .../cassandra/utils/memory/NativeAllocator.java    | 34 ++++++----------------
 .../cassandra/utils/memory/SlabAllocator.java      | 31 +++++---------------
 3 files changed, 18 insertions(+), 48 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index d94041b..a363005 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.21
+ * Avoid thread starvation, and improve compare-and-swap performance, in the 
slab allocators (CASSANDRA-15922)
  * Fix broken KEYS 2i queries after DROP COMPACT STORAGE (CASSANDRA-15906)
  * Add token to tombstone warning and error messages (CASSANDRA-15890)
  * Fixed range read concurrency factor computation and capped as 10 times tpc 
cores (CASSANDRA-15752)
diff --git a/src/java/org/apache/cassandra/utils/memory/NativeAllocator.java 
b/src/java/org/apache/cassandra/utils/memory/NativeAllocator.java
index 67f2a36..3d4ec16 100644
--- a/src/java/org/apache/cassandra/utils/memory/NativeAllocator.java
+++ b/src/java/org/apache/cassandra/utils/memory/NativeAllocator.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.db.DecoratedKey;
 import org.apache.cassandra.db.NativeDecoratedKey;
 import org.apache.cassandra.db.rows.Row;
@@ -188,11 +187,6 @@ public class NativeAllocator extends MemtableAllocator
         private AtomicInteger nextFreeOffset = new AtomicInteger(0);
 
         /**
-         * Total number of allocations satisfied from this buffer
-         */
-        private AtomicInteger allocCount = new AtomicInteger();
-
-        /**
          * Create an uninitialized region. Note that memory is not allocated 
yet, so
          * this is cheap.
          *
@@ -207,34 +201,24 @@ public class NativeAllocator extends MemtableAllocator
         /**
          * Try to allocate <code>size</code> bytes from the region.
          *
-         * @return the successful allocation, or null to indicate 
not-enough-space
+         * @return the successful allocation, or -1 to indicate 
not-enough-space
          */
         long allocate(int size)
         {
-            while (true)
-            {
-                int oldOffset = nextFreeOffset.get();
-
-                if (oldOffset + size > capacity) // capacity == remaining
-                    return -1;
-
-                // Try to atomically claim this region
-                if (nextFreeOffset.compareAndSet(oldOffset, oldOffset + size))
-                {
-                    // we got the alloc
-                    allocCount.incrementAndGet();
-                    return peer + oldOffset;
-                }
-                // we raced and lost alloc, try again
-            }
+            int newOffset = nextFreeOffset.getAndAdd(size);
+
+            if (newOffset + size > capacity)
+                // this region is full
+                return -1;
+
+            return peer + newOffset;
         }
 
         @Override
         public String toString()
         {
             return "Region@" + System.identityHashCode(this) +
-                    " allocs=" + allocCount.get() + "waste=" +
-                    (capacity - nextFreeOffset.get());
+                    "waste=" + Math.max(0, capacity - nextFreeOffset.get());
         }
     }
 
diff --git a/src/java/org/apache/cassandra/utils/memory/SlabAllocator.java 
b/src/java/org/apache/cassandra/utils/memory/SlabAllocator.java
index e797575..5a8ec18 100644
--- a/src/java/org/apache/cassandra/utils/memory/SlabAllocator.java
+++ b/src/java/org/apache/cassandra/utils/memory/SlabAllocator.java
@@ -172,11 +172,6 @@ public class SlabAllocator extends MemtableBufferAllocator
         private AtomicInteger nextFreeOffset = new AtomicInteger(0);
 
         /**
-         * Total number of allocations satisfied from this buffer
-         */
-        private AtomicInteger allocCount = new AtomicInteger();
-
-        /**
          * Create an uninitialized region. Note that memory is not allocated 
yet, so
          * this is cheap.
          *
@@ -194,30 +189,20 @@ public class SlabAllocator extends MemtableBufferAllocator
          */
         public ByteBuffer allocate(int size)
         {
-            while (true)
-            {
-                int oldOffset = nextFreeOffset.get();
-
-                if (oldOffset + size > data.capacity()) // capacity == 
remaining
-                    return null;
-
-                // Try to atomically claim this region
-                if (nextFreeOffset.compareAndSet(oldOffset, oldOffset + size))
-                {
-                    // we got the alloc
-                    allocCount.incrementAndGet();
-                    return (ByteBuffer) 
data.duplicate().position(oldOffset).limit(oldOffset + size);
-                }
-                // we raced and lost alloc, try again
-            }
+            int newOffset = nextFreeOffset.getAndAdd(size);
+
+            if (newOffset + size > data.capacity())
+                // this region is full
+                return null;
+
+            return (ByteBuffer) 
data.duplicate().position((newOffset)).limit(newOffset + size);
         }
 
         @Override
         public String toString()
         {
             return "Region@" + System.identityHashCode(this) +
-                   " allocs=" + allocCount.get() + "waste=" +
-                   (data.capacity() - nextFreeOffset.get());
+                   "waste=" + Math.max(0, data.capacity() - 
nextFreeOffset.get());
         }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to