Skip to content

Commit

Permalink
Reduce allocations by replacing AtomicInteger with AtomicIntegerField…
Browse files Browse the repository at this point in the history
…Updater (#2072)

Fixes #2071

When an app is running, a lot of RoutingContextImpl (and thus RoutingContextImplBase) instances are created.
With this change, we can save many AtomicInteger allocations.

Signed-off-by: Thomas Segismont <[email protected]>
  • Loading branch information
tsegismont authored Oct 21, 2021
1 parent ee861a9 commit 0cd7eca
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.web.*;
import io.vertx.ext.web.FileUpload;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.Session;
import io.vertx.ext.web.codec.impl.BodyCodecImpl;
import io.vertx.ext.web.handler.HttpException;
import io.vertx.ext.web.handler.impl.UserHolder;

import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

import static io.vertx.ext.web.handler.impl.SessionHandlerImpl.SESSION_USER_HOLDER_KEY;

Expand All @@ -42,9 +44,13 @@
*/
public class RoutingContextImpl extends RoutingContextImplBase {

private static final AtomicIntegerFieldUpdater<RoutingContextImpl> HANDLER_SEQ =
AtomicIntegerFieldUpdater.newUpdater(RoutingContextImpl.class, "handlerSeq");

private final RouterImpl router;
private final HttpServerRequest request;
private final AtomicInteger handlerSeq = new AtomicInteger();

private volatile int handlerSeq;

private Map<String, Object> data;
private Map<String, String> pathParams;
Expand Down Expand Up @@ -601,7 +607,7 @@ private Map<String, Object> getData() {
}

private int nextHandlerSeq() {
int seq = handlerSeq.incrementAndGet();
int seq = HANDLER_SEQ.incrementAndGet(this);
if (seq == Integer.MAX_VALUE) {
throw new IllegalStateException("Too many header/body end handlers!");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,25 @@

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
* @author <a href="http://tfox.org">Tim Fox</a>
*/
public abstract class RoutingContextImplBase implements RoutingContextInternal {

private static final AtomicIntegerFieldUpdater<RoutingContextImplBase> CURRENT_ROUTE_NEXT_HANDLER_INDEX =
AtomicIntegerFieldUpdater.newUpdater(RoutingContextImplBase.class, "currentRouteNextHandlerIndex");
private static final AtomicIntegerFieldUpdater<RoutingContextImplBase> CURRENT_ROUTE_NEXT_FAILURE_HANDLER_INDEX =
AtomicIntegerFieldUpdater.newUpdater(RoutingContextImplBase.class, "currentRouteNextFailureHandlerIndex");

protected static final Logger LOG = LoggerFactory.getLogger(RoutingContext.class);

private final Set<RouteImpl> routes;

protected final String mountPoint;
private final AtomicInteger currentRouteNextHandlerIndex;
private final AtomicInteger currentRouteNextFailureHandlerIndex;
private volatile int currentRouteNextHandlerIndex;
private volatile int currentRouteNextFailureHandlerIndex;
protected Iterator<RouteImpl> iter;
protected RouteState currentRoute;
// When Route#matches executes, if it returns != 0 this flag is configured
Expand All @@ -55,8 +60,6 @@ public abstract class RoutingContextImplBase implements RoutingContextInternal {
this.mountPoint = mountPoint;
this.routes = routes;
this.iter = routes.iterator();
this.currentRouteNextHandlerIndex = new AtomicInteger(0);
this.currentRouteNextFailureHandlerIndex = new AtomicInteger(0);
resetMatchFailure();
}

Expand Down Expand Up @@ -91,11 +94,11 @@ public Route currentRoute() {
}

int currentRouteNextHandlerIndex() {
return currentRouteNextHandlerIndex.intValue();
return currentRouteNextHandlerIndex;
}

int currentRouteNextFailureHandlerIndex() {
return currentRouteNextFailureHandlerIndex.intValue();
return currentRouteNextFailureHandlerIndex;
}

void restart() {
Expand All @@ -109,12 +112,12 @@ boolean iterateNext() {
if (currentRoute != null) { // Handle multiple handlers inside route object
try {
if (!failed && currentRoute.hasNextContextHandler(this)) {
currentRouteNextHandlerIndex.incrementAndGet();
CURRENT_ROUTE_NEXT_HANDLER_INDEX.incrementAndGet(this);
resetMatchFailure();
currentRoute.handleContext(this);
return true;
} else if (failed && currentRoute.hasNextFailureHandler(this)) {
currentRouteNextFailureHandlerIndex.incrementAndGet();
CURRENT_ROUTE_NEXT_FAILURE_HANDLER_INDEX.incrementAndGet(this);
currentRoute.handleFailure(this);
return true;
}
Expand All @@ -128,8 +131,8 @@ boolean iterateNext() {
// state is locked at this moment
RouteState routeState = iter.next().state();

currentRouteNextHandlerIndex.set(0);
currentRouteNextFailureHandlerIndex.set(0);
CURRENT_ROUTE_NEXT_HANDLER_INDEX.set(this, 0);
CURRENT_ROUTE_NEXT_FAILURE_HANDLER_INDEX.set(this, 0);
try {
int matchResult = routeState.matches(this, mountPoint(), failed);
if (matchResult == 0) {
Expand All @@ -144,10 +147,10 @@ boolean iterateNext() {
LOG.trace("Calling the " + (failed ? "failure" : "") + " handler");
}
if (failed && currentRoute.hasNextFailureHandler(this)) {
currentRouteNextFailureHandlerIndex.incrementAndGet();
CURRENT_ROUTE_NEXT_FAILURE_HANDLER_INDEX.incrementAndGet(this);
routeState.handleFailure(this);
} else if (currentRoute.hasNextContextHandler(this)) {
currentRouteNextHandlerIndex.incrementAndGet();
CURRENT_ROUTE_NEXT_HANDLER_INDEX.incrementAndGet(this);
routeState.handleContext(this);
} else {
continue;
Expand Down

0 comments on commit 0cd7eca

Please sign in to comment.