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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]