Skip to content

Commit 786fece

Browse files
committed
performance: netty
- redo context selector on multiple apps - nettystring fix hashcode implementation - get back previous leak detector (OFF) - rocker/fortunes tests remove composite buffer - ref #3770
1 parent 0de8aeb commit 786fece

File tree

10 files changed

+52
-55
lines changed

10 files changed

+52
-55
lines changed

jooby/src/main/java/io/jooby/Context.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,13 @@ interface Selector {
5050
/**
5151
* Select an application base on context path prefix matching a provided path.
5252
*
53-
* @param applications List of applications.
5453
* @param path Path to match.
5554
* @return Best match application.
5655
*/
57-
Jooby select(List<Jooby> applications, String path);
56+
Jooby select(String path);
5857

5958
static Selector create(List<Jooby> applications) {
60-
return applications.size() == 1 ? single() : multiple();
59+
return applications.size() == 1 ? single(applications.getFirst()) : multiple(applications);
6160
}
6261

6362
/**
@@ -66,9 +65,9 @@ static Selector create(List<Jooby> applications) {
6665
*
6766
* @return Best match application.
6867
*/
69-
static Selector multiple() {
70-
return (applications, path) -> {
71-
var defaultApp = applications.get(0);
68+
private static Selector multiple(List<Jooby> applications) {
69+
return path -> {
70+
var defaultApp = applications.getFirst();
7271
for (var app : applications) {
7372
var contextPath = app.getContextPath();
7473
if ("/".equals(contextPath)) {
@@ -81,8 +80,8 @@ static Selector multiple() {
8180
};
8281
}
8382

84-
private static Selector single() {
85-
return (applications, path) -> applications.get(0);
83+
private static Selector single(Jooby defaultApp) {
84+
return path -> defaultApp;
8685
}
8786
}
8887

modules/jooby-netty/src/main/java/io/jooby/internal/netty/HeadersMultiMap.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public HeadersMultiMap(BiConsumer<CharSequence, CharSequence> validator) {
8080

8181
public HeadersMultiMap add(CharSequence name, CharSequence value) {
8282
Objects.requireNonNull(value);
83-
int h = AsciiString.hashCode(name);
83+
int h = hashCode(name);
8484
int i = h & 0x0000000F;
8585
add0(h, i, name, value);
8686
return this;
@@ -102,7 +102,7 @@ public HeadersMultiMap add(String name, String strVal) {
102102

103103
@Override
104104
public HeadersMultiMap add(CharSequence name, Iterable values) {
105-
int h = AsciiString.hashCode(name);
105+
int h = hashCode(name);
106106
int i = h & 0x0000000F;
107107
for (Object vstr : values) {
108108
add0(h, i, name, toValidCharSequence(vstr));
@@ -118,7 +118,7 @@ public HeadersMultiMap add(String name, Iterable values) {
118118
@Override
119119
public HeadersMultiMap remove(CharSequence name) {
120120
Objects.requireNonNull(name, "name");
121-
int h = AsciiString.hashCode(name);
121+
int h = hashCode(name);
122122
int i = h & 0x0000000F;
123123
remove0(h, i, name);
124124
return this;
@@ -151,7 +151,7 @@ public HeadersMultiMap set(CharSequence name, Object value) {
151151
public HeadersMultiMap set(CharSequence name, Iterable values) {
152152
Objects.requireNonNull(values, "values");
153153

154-
int h = AsciiString.hashCode(name);
154+
int h = hashCode(name);
155155
int i = h & 0x0000000F;
156156

157157
remove0(h, i, name);
@@ -182,7 +182,7 @@ public boolean contains(CharSequence name, CharSequence value, boolean ignoreCas
182182

183183
private boolean containsInternal(
184184
CharSequence name, CharSequence value, boolean equals, boolean ignoreCase) {
185-
int h = AsciiString.hashCode(name);
185+
int h = hashCode(name);
186186
int i = h & 0x0000000F;
187187
HeadersMultiMap.MapEntry e = entries[i];
188188
while (e != null) {
@@ -257,7 +257,7 @@ public String get(String name) {
257257
public List<String> getAll(CharSequence name) {
258258
Objects.requireNonNull(name, "name");
259259
LinkedList<String> values = null;
260-
int h = AsciiString.hashCode(name);
260+
int h = hashCode(name);
261261
int i = h & 0x0000000F;
262262
HeadersMultiMap.MapEntry e = entries[i];
263263
while (e != null) {
@@ -606,7 +606,7 @@ private void add0(int h, int i, final CharSequence name, final CharSequence valu
606606
}
607607

608608
private HeadersMultiMap set0(final CharSequence name, final CharSequence strVal) {
609-
int h = AsciiString.hashCode(name);
609+
int h = hashCode(name);
610610
int i = h & 0x0000000F;
611611
remove0(h, i, name);
612612
if (strVal != null) {
@@ -616,7 +616,7 @@ private HeadersMultiMap set0(final CharSequence name, final CharSequence strVal)
616616
}
617617

618618
private CharSequence get0(CharSequence name) {
619-
int h = AsciiString.hashCode(name);
619+
int h = hashCode(name);
620620
int i = h & 0x0000000F;
621621
HeadersMultiMap.MapEntry e = entries[i];
622622
CharSequence value = null;
@@ -629,4 +629,8 @@ private CharSequence get0(CharSequence name) {
629629
}
630630
return value;
631631
}
632+
633+
private int hashCode(CharSequence value) {
634+
return value instanceof NettyString str ? str.hashCode() : AsciiString.hashCode(value);
635+
}
632636
}

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyHandler.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import static io.netty.handler.codec.http.HttpUtil.isTransferEncodingChunked;
1111

1212
import java.nio.charset.StandardCharsets;
13-
import java.util.List;
1413

1514
import org.slf4j.Logger;
1615
import org.slf4j.LoggerFactory;
@@ -27,9 +26,8 @@
2726
public class NettyHandler extends ChannelInboundHandlerAdapter {
2827
private final Logger log = LoggerFactory.getLogger(NettyServer.class);
2928
private final NettyDateService serverDate;
30-
private final List<Jooby> applications;
3129
private Router router;
32-
private final Context.Selector ctxSelector;
30+
private final Context.Selector contextSelector;
3331
private final int bufferSize;
3432
private final boolean defaultHeaders;
3533
private final long maxRequestSize;
@@ -40,14 +38,13 @@ public class NettyHandler extends ChannelInboundHandlerAdapter {
4038

4139
public NettyHandler(
4240
NettyDateService serverDate,
43-
List<Jooby> applications,
41+
Context.Selector contextSelector,
4442
long maxRequestSize,
4543
int bufferSize,
4644
boolean defaultHeaders,
4745
boolean http2) {
4846
this.serverDate = serverDate;
49-
this.applications = applications;
50-
this.ctxSelector = Context.Selector.create(applications);
47+
this.contextSelector = contextSelector;
5148
this.maxRequestSize = maxRequestSize;
5249
this.bufferSize = bufferSize;
5350
this.defaultHeaders = defaultHeaders;
@@ -59,7 +56,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
5956
if (isHttpRequest(msg)) {
6057
var req = (HttpRequest) msg;
6158
var path = pathOnly(req.uri());
62-
var app = ctxSelector.select(applications, path);
59+
var app = contextSelector.select(path);
6360
this.router = app.getRouter();
6461

6562
context = new NettyContext(ctx, req, app, path, bufferSize, http2);

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyPipeline.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
*/
66
package io.jooby.internal.netty;
77

8-
import java.util.List;
98
import java.util.concurrent.ScheduledExecutorService;
109
import java.util.function.Supplier;
1110

12-
import io.jooby.Jooby;
11+
import io.jooby.Context;
1312
import io.jooby.internal.netty.http2.NettyHttp2Configurer;
1413
import io.netty.channel.ChannelInitializer;
1514
import io.netty.channel.ChannelOutboundHandler;
@@ -22,7 +21,7 @@ public class NettyPipeline extends ChannelInitializer<SocketChannel> {
2221
private static final String H2_HANDSHAKE = "h2-handshake";
2322
private final SslContext sslContext;
2423
private final HttpDecoderConfig decoderConfig;
25-
private final List<Jooby> applications;
24+
private final Context.Selector contextSelector;
2625
private final long maxRequestSize;
2726
private final int bufferSize;
2827
private final boolean defaultHeaders;
@@ -33,7 +32,7 @@ public class NettyPipeline extends ChannelInitializer<SocketChannel> {
3332
public NettyPipeline(
3433
SslContext sslContext,
3534
HttpDecoderConfig decoderConfig,
36-
List<Jooby> applications,
35+
Context.Selector contextSelector,
3736
long maxRequestSize,
3837
int bufferSize,
3938
boolean defaultHeaders,
@@ -42,7 +41,7 @@ public NettyPipeline(
4241
Integer compressionLevel) {
4342
this.sslContext = sslContext;
4443
this.decoderConfig = decoderConfig;
45-
this.applications = applications;
44+
this.contextSelector = contextSelector;
4645
this.maxRequestSize = maxRequestSize;
4746
this.bufferSize = bufferSize;
4847
this.defaultHeaders = defaultHeaders;
@@ -54,7 +53,7 @@ public NettyPipeline(
5453
private NettyHandler createHandler(ScheduledExecutorService executor) {
5554
return new NettyHandler(
5655
new NettyDateService(executor),
57-
applications,
56+
contextSelector,
5857
maxRequestSize,
5958
bufferSize,
6059
defaultHeaders,

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyString.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import edu.umd.cs.findbugs.annotations.NonNull;
1111
import io.jooby.MediaType;
12+
import io.netty.util.AsciiString;
1213

1314
public class NettyString implements CharSequence {
1415
static final CharSequence server = NettyString.of("N");
@@ -23,11 +24,13 @@ public class NettyString implements CharSequence {
2324
final byte[] bytes;
2425
private final String value;
2526
private final int hashCode;
27+
private final int length;
2628

2729
public NettyString(String value) {
2830
this.value = value;
29-
this.hashCode = value.hashCode();
31+
this.hashCode = AsciiString.hashCode(value);
3032
this.bytes = value.getBytes(StandardCharsets.US_ASCII);
33+
this.length = value.length();
3134
}
3235

3336
public static NettyString of(String value) {
@@ -36,7 +39,7 @@ public static NettyString of(String value) {
3639

3740
@Override
3841
public int length() {
39-
return value.length();
42+
return length;
4043
}
4144

4245
@Override

modules/jooby-netty/src/main/java/io/jooby/netty/NettyServer.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@
1717
import javax.net.ssl.SSLContext;
1818

1919
import edu.umd.cs.findbugs.annotations.NonNull;
20-
import io.jooby.Jooby;
21-
import io.jooby.Server;
22-
import io.jooby.ServerOptions;
23-
import io.jooby.SneakyThrows;
24-
import io.jooby.SslOptions;
20+
import io.jooby.*;
2521
import io.jooby.exception.StartupException;
2622
import io.jooby.internal.netty.*;
2723
import io.jooby.output.OutputFactory;
@@ -36,6 +32,7 @@
3632
import io.netty.handler.ssl.IdentityCipherSuiteFilter;
3733
import io.netty.handler.ssl.JdkSslContext;
3834
import io.netty.handler.ssl.SslContext;
35+
import io.netty.util.ResourceLeakDetector;
3936
import io.netty.util.concurrent.DefaultThreadFactory;
4037

4138
/**
@@ -47,9 +44,15 @@
4744
public class NettyServer extends Server.Base {
4845

4946
private static final String NAME = "netty";
47+
private static final String LEAK_DETECTION = "io.netty.leakDetection.level";
5048

5149
static {
5250
System.setProperty("__server_.name", NAME);
51+
System.setProperty(
52+
LEAK_DETECTION,
53+
System.getProperty(LEAK_DETECTION, ResourceLeakDetector.Level.DISABLED.name()));
54+
ResourceLeakDetector.setLevel(
55+
ResourceLeakDetector.Level.valueOf(System.getProperty(LEAK_DETECTION)));
5356
}
5457

5558
private NettyEventLoopGroup eventLoop;
@@ -208,7 +211,7 @@ private NettyPipeline newPipeline(ServerOptions options, SslContext sslContext,
208211
return new NettyPipeline(
209212
sslContext,
210213
decoderConfig,
211-
applications,
214+
Context.Selector.create(applications),
212215
options.getMaxRequestSize(),
213216
options.getOutput().getSize(),
214217
options.getDefaultHeaders(),

modules/jooby-rocker/src/main/java/io/jooby/rocker/BufferedRockerOutput.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,6 @@ public Output asOutput() {
7474

7575
static RockerOutputFactory<BufferedRockerOutput> factory(Charset charset, OutputFactory factory) {
7676
return (contentType, charsetName) ->
77-
new BufferedRockerOutput(charset, contentType, factory.newComposite());
77+
new BufferedRockerOutput(charset, contentType, factory.allocate());
7878
}
7979
}

modules/jooby-undertow/src/main/java/io/jooby/internal/undertow/UndertowHandler.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package io.jooby.internal.undertow;
77

88
import java.nio.charset.StandardCharsets;
9-
import java.util.List;
109

1110
import io.jooby.*;
1211
import io.undertow.io.Receiver;
@@ -20,24 +19,25 @@
2019
import io.undertow.util.Headers;
2120

2221
public class UndertowHandler implements HttpHandler {
23-
protected final List<Jooby> applications;
2422
private final long maxRequestSize;
2523
private final int bufferSize;
2624
private final boolean defaultHeaders;
2725
private final Context.Selector ctxSelector;
2826

2927
public UndertowHandler(
30-
List<Jooby> applications, int bufferSize, long maxRequestSize, boolean defaultHeaders) {
31-
this.applications = applications;
32-
this.ctxSelector = Context.Selector.create(applications);
28+
Context.Selector contextSelector,
29+
int bufferSize,
30+
long maxRequestSize,
31+
boolean defaultHeaders) {
32+
this.ctxSelector = contextSelector;
3333
this.maxRequestSize = maxRequestSize;
3434
this.bufferSize = bufferSize;
3535
this.defaultHeaders = defaultHeaders;
3636
}
3737

3838
@Override
3939
public void handleRequest(HttpServerExchange exchange) throws Exception {
40-
var router = ctxSelector.select(applications, exchange.getRequestPath());
40+
var router = ctxSelector.select(exchange.getRequestPath());
4141
var context = new UndertowContext(exchange, router);
4242

4343
/* default headers: */

modules/jooby-undertow/src/main/java/io/jooby/undertow/UndertowServer.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@
1616
import org.xnio.*;
1717

1818
import edu.umd.cs.findbugs.annotations.NonNull;
19-
import io.jooby.Jooby;
20-
import io.jooby.Server;
21-
import io.jooby.ServerOptions;
22-
import io.jooby.SneakyThrows;
23-
import io.jooby.SslOptions;
19+
import io.jooby.*;
2420
import io.jooby.exception.StartupException;
2521
import io.jooby.internal.undertow.UndertowHandler;
2622
import io.jooby.internal.undertow.UndertowWebSocket;
@@ -100,7 +96,7 @@ public String getName() {
10096

10197
HttpHandler handler =
10298
new UndertowHandler(
103-
this.applications,
99+
Context.Selector.create(applications),
104100
getOptions().getOutput().getSize(),
105101
options.getMaxRequestSize(),
106102
options.getDefaultHeaders());

tests/src/test/java/examples/Performance.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ public class Performance extends Jooby {
4343

4444
public static void main(final String[] args) {
4545
System.setProperty("io.netty.disableHttpHeadersValidation", "true");
46-
runApp(
47-
args,
48-
new NettyServer(new ServerOptions()).setSingleEventLoopGroup(true),
49-
EVENT_LOOP,
50-
Performance::new);
46+
runApp(args, new NettyServer(new ServerOptions()), EVENT_LOOP, Performance::new);
5147
}
5248
}

0 commit comments

Comments
 (0)