From 80aab00dc5b7a36785f5e09b6a54397388980cde Mon Sep 17 00:00:00 2001 From: cpovirk Date: Fri, 10 Jan 2025 14:43:40 -0800 Subject: [PATCH] Remove `Unsafe`-based implementation from `ExecutionListBenchmark`. It's nice to have, but it's not worth going to any trouble for in the face of the ongoing work to remove the `Unsafe` APIs. RELNOTES=n/a PiperOrigin-RevId: 714178045 --- .../concurrent/ExecutionListBenchmark.java | 151 ------------------ .../concurrent/ExecutionListBenchmark.java | 151 ------------------ 2 files changed, 302 deletions(-) diff --git a/android/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java b/android/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java index 227ad99be874..a1db2b6c0242 100644 --- a/android/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java +++ b/android/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java @@ -29,10 +29,6 @@ import com.google.common.collect.Lists; import com.google.common.util.concurrent.AbstractFutureBenchmarks.OldAbstractFuture; import com.google.errorprone.annotations.concurrent.GuardedBy; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CountDownLatch; @@ -44,7 +40,6 @@ import java.util.logging.Logger; import org.jspecify.annotations.NullUnmarked; import org.jspecify.annotations.Nullable; -import sun.misc.Unsafe; /** Benchmarks for {@link ExecutionList}. */ @VmOptions({"-Xms8g", "-Xmx8g"}) @@ -85,29 +80,6 @@ public Object getImpl() { }; } }, - NEW_WITH_CAS { - @Override - ExecutionListWrapper newExecutionList() { - return new ExecutionListWrapper() { - final ExecutionListUsingCompareAndSwap list = new ExecutionListUsingCompareAndSwap(); - - @Override - public void add(Runnable runnable, Executor executor) { - list.add(runnable, executor); - } - - @Override - public void execute() { - list.execute(); - } - - @Override - public Object getImpl() { - return list; - } - }; - } - }, NEW_WITH_QUEUE { @Override ExecutionListWrapper newExecutionList() { @@ -578,127 +550,4 @@ private static final class RunnableExecutorPair { } } } - - // A version of the list that uses compare and swap to manage the stack without locks. - @SuppressWarnings({"SunApi", "removal"}) // b/345822163 - private static final class ExecutionListUsingCompareAndSwap { - static final Logger log = Logger.getLogger(ExecutionListUsingCompareAndSwap.class.getName()); - - private static final Unsafe UNSAFE; - private static final long HEAD_OFFSET; - - /** - * A special instance of {@link RunnableExecutorPair} that is used as a sentinel value for the - * bottom of the stack. - */ - private static final RunnableExecutorPair NULL_PAIR = new RunnableExecutorPair(null, null); - - static { - try { - UNSAFE = getUnsafe(); - HEAD_OFFSET = - UNSAFE.objectFieldOffset( - ExecutionListUsingCompareAndSwap.class.getDeclaredField("head")); - } catch (Exception ex) { - throw new Error(ex); - } - } - - /** TODO(lukes): This was copied verbatim from Striped64.java... standardize this? */ - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) { - } - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - @Override - public Unsafe run() throws Exception { - Class k = Unsafe.class; - for (Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - } - }); - } catch (PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", e.getCause()); - } - } - - private volatile RunnableExecutorPair head = NULL_PAIR; - - public void add(Runnable runnable, Executor executor) { - Preconditions.checkNotNull(runnable, "Runnable was null."); - Preconditions.checkNotNull(executor, "Executor was null."); - - RunnableExecutorPair newHead = new RunnableExecutorPair(runnable, executor); - RunnableExecutorPair oldHead; - do { - oldHead = head; - if (oldHead == null) { - // If runnables == null then execute() has been called so we should just execute our - // listener immediately. - newHead.execute(); - return; - } - // Try to make newHead the new head of the stack at runnables. - newHead.next = oldHead; - } while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, oldHead, newHead)); - } - - public void execute() { - RunnableExecutorPair stack; - do { - stack = head; - if (stack == null) { - // If head == null then execute() has been called so we should just return - return; - } - // try to swap null into head. - } while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, stack, null)); - - RunnableExecutorPair reversedStack = null; - while (stack != NULL_PAIR) { - RunnableExecutorPair head = stack; - stack = stack.next; - head.next = reversedStack; - reversedStack = head; - } - stack = reversedStack; - while (stack != null) { - stack.execute(); - stack = stack.next; - } - } - - private static class RunnableExecutorPair { - final Runnable runnable; - final Executor executor; - // Volatile because this is written on one thread and read on another with no synchronization. - @Nullable volatile RunnableExecutorPair next; - - RunnableExecutorPair(@Nullable Runnable runnable, @Nullable Executor executor) { - this.runnable = runnable; - this.executor = executor; - } - - void execute() { - try { - executor.execute(runnable); - } catch (RuntimeException e) { - log.log( - Level.SEVERE, - "RuntimeException while executing runnable " - + runnable - + " with executor " - + executor, - e); - } - } - } - } } diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java index 227ad99be874..a1db2b6c0242 100644 --- a/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java +++ b/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java @@ -29,10 +29,6 @@ import com.google.common.collect.Lists; import com.google.common.util.concurrent.AbstractFutureBenchmarks.OldAbstractFuture; import com.google.errorprone.annotations.concurrent.GuardedBy; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CountDownLatch; @@ -44,7 +40,6 @@ import java.util.logging.Logger; import org.jspecify.annotations.NullUnmarked; import org.jspecify.annotations.Nullable; -import sun.misc.Unsafe; /** Benchmarks for {@link ExecutionList}. */ @VmOptions({"-Xms8g", "-Xmx8g"}) @@ -85,29 +80,6 @@ public Object getImpl() { }; } }, - NEW_WITH_CAS { - @Override - ExecutionListWrapper newExecutionList() { - return new ExecutionListWrapper() { - final ExecutionListUsingCompareAndSwap list = new ExecutionListUsingCompareAndSwap(); - - @Override - public void add(Runnable runnable, Executor executor) { - list.add(runnable, executor); - } - - @Override - public void execute() { - list.execute(); - } - - @Override - public Object getImpl() { - return list; - } - }; - } - }, NEW_WITH_QUEUE { @Override ExecutionListWrapper newExecutionList() { @@ -578,127 +550,4 @@ private static final class RunnableExecutorPair { } } } - - // A version of the list that uses compare and swap to manage the stack without locks. - @SuppressWarnings({"SunApi", "removal"}) // b/345822163 - private static final class ExecutionListUsingCompareAndSwap { - static final Logger log = Logger.getLogger(ExecutionListUsingCompareAndSwap.class.getName()); - - private static final Unsafe UNSAFE; - private static final long HEAD_OFFSET; - - /** - * A special instance of {@link RunnableExecutorPair} that is used as a sentinel value for the - * bottom of the stack. - */ - private static final RunnableExecutorPair NULL_PAIR = new RunnableExecutorPair(null, null); - - static { - try { - UNSAFE = getUnsafe(); - HEAD_OFFSET = - UNSAFE.objectFieldOffset( - ExecutionListUsingCompareAndSwap.class.getDeclaredField("head")); - } catch (Exception ex) { - throw new Error(ex); - } - } - - /** TODO(lukes): This was copied verbatim from Striped64.java... standardize this? */ - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) { - } - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - @Override - public Unsafe run() throws Exception { - Class k = Unsafe.class; - for (Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - } - }); - } catch (PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", e.getCause()); - } - } - - private volatile RunnableExecutorPair head = NULL_PAIR; - - public void add(Runnable runnable, Executor executor) { - Preconditions.checkNotNull(runnable, "Runnable was null."); - Preconditions.checkNotNull(executor, "Executor was null."); - - RunnableExecutorPair newHead = new RunnableExecutorPair(runnable, executor); - RunnableExecutorPair oldHead; - do { - oldHead = head; - if (oldHead == null) { - // If runnables == null then execute() has been called so we should just execute our - // listener immediately. - newHead.execute(); - return; - } - // Try to make newHead the new head of the stack at runnables. - newHead.next = oldHead; - } while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, oldHead, newHead)); - } - - public void execute() { - RunnableExecutorPair stack; - do { - stack = head; - if (stack == null) { - // If head == null then execute() has been called so we should just return - return; - } - // try to swap null into head. - } while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, stack, null)); - - RunnableExecutorPair reversedStack = null; - while (stack != NULL_PAIR) { - RunnableExecutorPair head = stack; - stack = stack.next; - head.next = reversedStack; - reversedStack = head; - } - stack = reversedStack; - while (stack != null) { - stack.execute(); - stack = stack.next; - } - } - - private static class RunnableExecutorPair { - final Runnable runnable; - final Executor executor; - // Volatile because this is written on one thread and read on another with no synchronization. - @Nullable volatile RunnableExecutorPair next; - - RunnableExecutorPair(@Nullable Runnable runnable, @Nullable Executor executor) { - this.runnable = runnable; - this.executor = executor; - } - - void execute() { - try { - executor.execute(runnable); - } catch (RuntimeException e) { - log.log( - Level.SEVERE, - "RuntimeException while executing runnable " - + runnable - + " with executor " - + executor, - e); - } - } - } - } }