diff --git a/src/main/java/org/jboss/threads/EnhancedQueueExecutor.java b/src/main/java/org/jboss/threads/EnhancedQueueExecutor.java index 3ce0b001..2300fea4 100644 --- a/src/main/java/org/jboss/threads/EnhancedQueueExecutor.java +++ b/src/main/java/org/jboss/threads/EnhancedQueueExecutor.java @@ -47,7 +47,6 @@ import javax.management.ObjectInstance; import javax.management.ObjectName; -import io.smallrye.common.cpu.CacheInfo; import org.jboss.threads.management.ManageableThreadPoolExecutorService; import org.jboss.threads.management.StandardThreadPoolMXBean; @@ -337,23 +336,31 @@ private static final class RuntimeFields { private static final long queueSizeOffset; static { - int cacheLine = CacheInfo.getSmallestDataCacheLineSize(); - if (cacheLine == 0) { - // guess - cacheLine = 64; - } - // cpu spatial prefetcher can drag 2 cache-lines at once into L2 - int pad = cacheLine > 128 ? cacheLine : 128; int longScale = unsafe.arrayIndexScale(long[].class); int taskNodeScale = unsafe.arrayIndexScale(TaskNode[].class); - // these fields are in units of array scale - unsharedTaskNodesSize = pad / taskNodeScale * (numUnsharedObjects + 1); - unsharedLongsSize = pad / longScale * (numUnsharedLongs + 1); - // these fields are in bytes - headOffset = unsafe.arrayBaseOffset(TaskNode[].class) + pad; - tailOffset = unsafe.arrayBaseOffset(TaskNode[].class) + pad * 2; - threadStatusOffset = unsafe.arrayBaseOffset(long[].class) + pad; - queueSizeOffset = unsafe.arrayBaseOffset(long[].class) + pad * 2; + if (ProcessorInfo.availableProcessors() > 1) { + // this is fine for pretty much 32 and 64 bit x86 and ARM processors; see + // https://github.com/ziglang/zig/blob/0.13.0/lib/std/atomic.zig#L424-L434 + // cpu spatial prefetcher can drag 2 cache-lines at once into L2 + int pad = 128; + // we both pad before and after the array to avoid false sharing with surrounding heap objects + unsharedTaskNodesSize = pad / taskNodeScale * (numUnsharedObjects + 1); + unsharedLongsSize = pad / longScale * (numUnsharedLongs + 1); + // these fields are in bytes + headOffset = unsafe.arrayBaseOffset(TaskNode[].class) + pad; + tailOffset = unsafe.arrayBaseOffset(TaskNode[].class) + pad * 2; + threadStatusOffset = unsafe.arrayBaseOffset(long[].class) + pad; + queueSizeOffset = unsafe.arrayBaseOffset(long[].class) + pad * 2; + } else { + unsharedTaskNodesSize = numUnsharedObjects; + unsharedLongsSize = numUnsharedLongs; + // position 0 + headOffset = unsafe.arrayBaseOffset(TaskNode[].class); + // position 1 in the object array + tailOffset = unsafe.arrayBaseOffset(TaskNode[].class) + taskNodeScale; + threadStatusOffset = unsafe.arrayBaseOffset(long[].class); + queueSizeOffset = unsafe.arrayBaseOffset(long[].class) + longScale; + } } }