1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.testsuite.svm;
17
18 import io.netty.bootstrap.ServerBootstrap;
19 import io.netty.buffer.AdaptiveByteBufAllocator;
20 import io.netty.buffer.ByteBufAllocator;
21 import io.netty.buffer.PooledByteBufAllocator;
22 import io.netty.buffer.UnpooledByteBufAllocator;
23 import io.netty.channel.Channel;
24 import io.netty.channel.ChannelOption;
25 import io.netty.channel.EventLoopGroup;
26 import io.netty.channel.IoHandlerFactory;
27 import io.netty.channel.MultiThreadIoEventLoopGroup;
28 import io.netty.channel.epoll.EpollIoHandler;
29 import io.netty.channel.epoll.EpollServerSocketChannel;
30 import io.netty.channel.epoll.EpollSocketChannel;
31 import io.netty.channel.nio.NioIoHandler;
32 import io.netty.channel.socket.ServerSocketChannel;
33 import io.netty.channel.socket.nio.NioServerSocketChannel;
34 import io.netty.channel.socket.nio.NioSocketChannel;
35 import io.netty.channel.uring.IoUring;
36 import io.netty.channel.uring.IoUringBufferRingConfig;
37 import io.netty.channel.uring.IoUringFixedBufferRingAllocator;
38 import io.netty.channel.uring.IoUringIoHandler;
39 import io.netty.channel.uring.IoUringIoHandlerConfig;
40 import io.netty.channel.uring.IoUringServerSocketChannel;
41 import io.netty.channel.uring.IoUringSocketChannel;
42 import io.netty.handler.codec.http.DefaultFullHttpRequest;
43 import io.netty.handler.codec.http.HttpMethod;
44 import io.netty.handler.codec.http.HttpVersion;
45 import io.netty.handler.logging.LogLevel;
46 import io.netty.handler.logging.LoggingHandler;
47
48 import java.net.InetSocketAddress;
49 import java.util.concurrent.CompletableFuture;
50
51
52
53
54
55 public final class HttpNativeServer {
56
57
58
59
60 private HttpNativeServer() {
61 }
62
63 public static void main(String[] args) throws Exception {
64 for (TransportType value : TransportType.values()) {
65 for (AllocatorType allocatorType : AllocatorType.values()) {
66 boolean serverStartSucess = testTransport(value, allocatorType);
67 System.out.println("Server started with transport type " + value + ": " + serverStartSucess);
68 if (!serverStartSucess) {
69 System.exit(1);
70 }
71 }
72 }
73
74 System.exit(0);
75 }
76
77 public static boolean testTransport(TransportType ioType, AllocatorType allocatorType) throws Exception {
78
79 EventLoopGroup bossGroup = new MultiThreadIoEventLoopGroup(1, chooseFactory(ioType));
80 EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(chooseFactory(ioType));
81
82 boolean serverStartSucess = false;
83 try {
84 CompletableFuture<Void> httpRequestFuture = new CompletableFuture<>();
85 ServerBootstrap b = new ServerBootstrap();
86 b.option(ChannelOption.SO_BACKLOG, 1024);
87 b.group(bossGroup, workerGroup)
88 .channel(chooseServerChannelClass(ioType))
89 .handler(new LoggingHandler(LogLevel.INFO))
90 .childOption(ChannelOption.ALLOCATOR, chooseAllocator(allocatorType))
91 .childHandler(new HttpNativeServerInitializer(httpRequestFuture));
92
93 Channel channel = b.bind(0).sync().channel();
94 System.err.println("Server started, will shutdown now.");
95
96 Channel httpClient = new HttpNativeClient(
97 ((InetSocketAddress) channel.localAddress()).getPort(),
98 workerGroup, chooseChannelClass(ioType)
99 ).initClient();
100 DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/hello");
101
102 httpClient.writeAndFlush(request).sync();
103
104 httpRequestFuture.get();
105
106 channel.close().sync();
107 httpClient.close().sync();
108 serverStartSucess = true;
109 } finally {
110 bossGroup.shutdownGracefully();
111 workerGroup.shutdownGracefully();
112 }
113 return serverStartSucess;
114 }
115
116 public static IoHandlerFactory chooseFactory(TransportType ioType) {
117 if (ioType == TransportType.EPOLL) {
118 return EpollIoHandler.newFactory();
119 }
120
121 if (ioType == TransportType.IO_URING) {
122 IoUringIoHandlerConfig config = new IoUringIoHandlerConfig();
123 if (IoUring.isRegisterBufferRingSupported()) {
124 config.setBufferRingConfig(new IoUringBufferRingConfig(
125 (short) 0, (short) 16, 16 * 16,
126 new IoUringFixedBufferRingAllocator(1024)
127 ));
128 }
129
130 return IoUringIoHandler.newFactory(config);
131 }
132
133 return NioIoHandler.newFactory();
134 }
135
136 public static ByteBufAllocator chooseAllocator(AllocatorType allocatorType) {
137 switch (allocatorType) {
138 case POOLED : return PooledByteBufAllocator.DEFAULT;
139 case UNPOOLED : return UnpooledByteBufAllocator.DEFAULT;
140 case ADAPTIVE: return new AdaptiveByteBufAllocator();
141 default: return PooledByteBufAllocator.DEFAULT;
142 }
143 }
144
145 public static Class<? extends ServerSocketChannel> chooseServerChannelClass(TransportType ioType) {
146 if (ioType == TransportType.EPOLL) {
147 return EpollServerSocketChannel.class;
148 }
149
150 if (ioType == TransportType.IO_URING) {
151 return IoUringServerSocketChannel.class;
152 }
153
154 return NioServerSocketChannel.class;
155 }
156
157 public static Class<? extends Channel> chooseChannelClass(TransportType ioType) {
158 if (ioType == TransportType.EPOLL) {
159 return EpollSocketChannel.class;
160 }
161
162 if (ioType == TransportType.IO_URING) {
163 return IoUringSocketChannel.class;
164 }
165
166 return NioSocketChannel.class;
167 }
168
169 enum TransportType {
170 NIO,
171 EPOLL,
172 IO_URING,
173 }
174
175 enum AllocatorType {
176 POOLED,
177 UNPOOLED,
178 ADAPTIVE
179 }
180 }