diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java index e74a5f86e6e0..b50095800557 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java @@ -196,7 +196,7 @@ public AbstractConnector( int cores = ProcessorUtils.availableProcessors(); if (acceptors < 0) - acceptors = Math.max(1, Math.min(4, cores / 8)); + acceptors = 1; if (acceptors > cores) LOG.warn("Acceptors should be <= availableProcessors: {} ", this); _acceptors = new Thread[acceptors]; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java index 88e95e90c356..47730795b4a7 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java @@ -48,7 +48,7 @@ public class LocalConnector extends AbstractConnector public LocalConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool bufferPool, int acceptors, ConnectionFactory... factories) { - super(server, executor, scheduler, bufferPool, acceptors, factories); + super(server, executor, scheduler, bufferPool, Math.max(1, acceptors), factories); setIdleTimeout(30000); } diff --git a/jetty-core/jetty-unixdomain-server/src/main/java/org/eclipse/jetty/unixdomain/server/UnixDomainServerConnector.java b/jetty-core/jetty-unixdomain-server/src/main/java/org/eclipse/jetty/unixdomain/server/UnixDomainServerConnector.java index b1665e433f31..8fa783e94882 100644 --- a/jetty-core/jetty-unixdomain-server/src/main/java/org/eclipse/jetty/unixdomain/server/UnixDomainServerConnector.java +++ b/jetty-core/jetty-unixdomain-server/src/main/java/org/eclipse/jetty/unixdomain/server/UnixDomainServerConnector.java @@ -149,9 +149,17 @@ public void setAcceptedSendBufferSize(int acceptedSendBufferSize) protected void doStart() throws Exception { getBeans(SelectorManager.SelectorManagerListener.class).forEach(selectorManager::addEventListener); + serverChannel = open(); addBean(serverChannel); + super.doStart(); + + if (getAcceptors() == 0) + { + serverChannel.configureBlocking(false); + acceptor.set(selectorManager.acceptor(serverChannel)); + } } @Override @@ -200,25 +208,6 @@ public Object getTransport() } private ServerSocketChannel open() throws IOException - { - ServerSocketChannel serverChannel = openServerSocketChannel(); - if (getAcceptors() == 0) - { - serverChannel.configureBlocking(false); - acceptor.set(selectorManager.acceptor(serverChannel)); - } - return serverChannel; - } - - private void close() throws IOException - { - ServerSocketChannel serverChannel = this.serverChannel; - this.serverChannel = null; - IO.close(serverChannel); - Files.deleteIfExists(getUnixDomainPath()); - } - - private ServerSocketChannel openServerSocketChannel() throws IOException { ServerSocketChannel serverChannel = null; if (isInheritChannel()) @@ -234,6 +223,14 @@ private ServerSocketChannel openServerSocketChannel() throws IOException return serverChannel; } + private void close() throws IOException + { + ServerSocketChannel serverChannel = this.serverChannel; + this.serverChannel = null; + IO.close(serverChannel); + Files.deleteIfExists(getUnixDomainPath()); + } + private ServerSocketChannel bindServerSocketChannel() throws IOException { Path unixDomainPath = getUnixDomainPath(); diff --git a/tests/jetty-jmh/pom.xml b/tests/jetty-jmh/pom.xml index 7348d0ef9db0..44d7932f9238 100644 --- a/tests/jetty-jmh/pom.xml +++ b/tests/jetty-jmh/pom.xml @@ -29,6 +29,10 @@ org.eclipse.jetty jetty-server + + org.eclipse.jetty + jetty-slf4j-impl + org.eclipse.jetty jetty-util @@ -51,11 +55,6 @@ org.slf4j slf4j-api - - org.eclipse.jetty - jetty-slf4j-impl - test - diff --git a/tests/jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ServerConnectorAcceptBenchmark.java b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ServerConnectorAcceptBenchmark.java new file mode 100644 index 000000000000..ce25ab8ca18b --- /dev/null +++ b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ServerConnectorAcceptBenchmark.java @@ -0,0 +1,110 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.server.jmh; + +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.LongAdder; + +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpTester; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.util.Callback; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.openjdk.jmh.runner.options.TimeValue; + +@State(Scope.Benchmark) +public class ServerConnectorAcceptBenchmark +{ + public static void main(String[] args) throws Exception + { + Options opt = new OptionsBuilder() + .include(ServerConnectorAcceptBenchmark.class.getSimpleName()) + .warmupIterations(10) + .warmupTime(TimeValue.milliseconds(500)) + .measurementIterations(10) + .measurementTime(TimeValue.milliseconds(500)) + .forks(1) + .threads(20) + .build(); + new Runner(opt).run(); + } + +// @Param({"0", "1", "2", "4"}) + @Param({"4", "2", "1", "0"}) + public int acceptors; + + final LongAdder count = new LongAdder(); + + Server server; + ServerConnector connector; + + @Setup + public void prepare() throws Exception + { + server = new Server(); + connector = new ServerConnector(server, acceptors, -1); + server.addConnector(connector); + server.setHandler(new Handler.Abstract() + { + @Override + public boolean handle(Request request, Response response, Callback callback) throws Exception + { + callback.succeeded(); + return true; + } + }); + server.start(); + } + + @TearDown + public void dispose() throws Exception + { + System.err.println("count = " + count.sum()); + server.stop(); + } + + @Benchmark + @BenchmarkMode({Mode.Throughput}) + public void accept() throws Exception + { + count.increment(); + try (SocketChannel channel = SocketChannel.open(new InetSocketAddress("localhost", connector.getLocalPort()))) + { + channel.write(StandardCharsets.US_ASCII.encode("GET / HTTP/1.0\r\n\r\n")); + HttpTester.Response response = HttpTester.parseResponse(HttpTester.from(channel)); + if (response.getStatus() != HttpStatus.OK_200) + System.err.println("x = " + response); + } + catch (Throwable x) + { + System.err.println("x = " + x); + } + } +}