Skip to content

Commit c0c0bc7

Browse files
re-thcvietj
authored andcommitted
Optimize InternalTimerHandler disposed state handling
Motivation: InternalTimerHandler used AtomicBoolean for disposal tracking, which adds an object allocation and extra indirection in a hot timer path. Changes: - Replaced the per-instance AtomicBoolean disposed field with a volatile boolean field. - Added a static VarHandle for InternalTimerHandler.disposed and a disposedCAS helper to preserve atomic compare-and-set behavior where required. - Kept periodic timer execution checks as volatile reads while retaining one-shot/cancel atomicity. Results: mvn -pl vertx-core -DskipTests compile passes.
1 parent 7b530f9 commit c0c0bc7

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@
8080
import java.nio.charset.StandardCharsets;
8181
import java.util.*;
8282
import java.util.concurrent.*;
83-
import java.util.concurrent.atomic.AtomicBoolean;
8483
import java.util.concurrent.atomic.AtomicInteger;
8584
import java.util.concurrent.atomic.AtomicLong;
8685
import java.util.function.Function;
@@ -107,13 +106,27 @@ public class VertxImpl implements VertxInternal, MetricsProvider {
107106
// https://github.com/eclipse-vertx/vert.x/issues/4611
108107

109108
private static final Logger log = LoggerFactory.getLogger(VertxImpl.class);
109+
private static final VarHandle INTERNAL_TIMER_HANDLER_DISPOSED;
110+
111+
static {
112+
try {
113+
INTERNAL_TIMER_HANDLER_DISPOSED = MethodHandles.lookup()
114+
.findVarHandle(InternalTimerHandler.class, "disposed", boolean.class);
115+
} catch (NoSuchFieldException | IllegalAccessException e) {
116+
throw new IllegalArgumentException(e);
117+
}
118+
}
110119

111120
static final Object[] EMPTY_CONTEXT_LOCALS = new Object[0];
112121
private static final String CLUSTER_MAP_NAME = "__vertx.haInfo";
113122
private static final String NETTY_IO_RATIO_PROPERTY_NAME = "vertx.nettyIORatio";
114123
private static final int NETTY_IO_RATIO = Integer.getInteger(NETTY_IO_RATIO_PROPERTY_NAME, 50);
115124
private static final VarHandle LOCALS_UPDATER = MethodHandles.arrayElementVarHandle(EventLoop[].class);
116125

126+
private static boolean disposedCAS(InternalTimerHandler handler) {
127+
return INTERNAL_TIMER_HANDLER_DISPOSED.compareAndSet(handler, false, true);
128+
}
129+
117130
// Not cached for graalvm
118131
private static ThreadFactory virtualThreadFactory() {
119132
try {
@@ -1044,7 +1057,7 @@ class InternalTimerHandler implements Handler<Void>, Closeable, Runnable {
10441057
private final boolean periodic;
10451058
private final long id;
10461059
private final ContextInternal context;
1047-
private final AtomicBoolean disposed = new AtomicBoolean();
1060+
private volatile boolean disposed;
10481061
private volatile java.util.concurrent.Future<?> future;
10491062

10501063
InternalTimerHandler(long id, Handler<Long> runnable, boolean periodic, ContextInternal context) {
@@ -1065,10 +1078,10 @@ public void run() {
10651078

10661079
public void handle(Void v) {
10671080
if (periodic) {
1068-
if (!disposed.get()) {
1081+
if (!disposed) {
10691082
handler.handle(id);
10701083
}
1071-
} else if (disposed.compareAndSet(false, true)) {
1084+
} else if (disposedCAS(this)) {
10721085
timeouts.remove(id);
10731086
try {
10741087
handler.handle(id);
@@ -1090,7 +1103,7 @@ private boolean cancel() {
10901103
}
10911104

10921105
private boolean tryCancel() {
1093-
if (disposed.compareAndSet(false, true)) {
1106+
if (disposedCAS(this)) {
10941107
timeouts.remove(id);
10951108
future.cancel(false);
10961109
return true;

0 commit comments

Comments
 (0)