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 group = new MultiThreadIoEventLoopGroup(chooseFactory(ioType));
80
81 boolean serverStartSucess = false;
82 try {
83 CompletableFuture<Void> httpRequestFuture = new CompletableFuture<>();
84 ServerBootstrap b = new ServerBootstrap();
85 b.option(ChannelOption.SO_BACKLOG, 1024);
86 b.group(group)
87 .channel(chooseServerChannelClass(ioType))
88 .handler(new LoggingHandler(LogLevel.INFO))
89 .childOption(ChannelOption.ALLOCATOR, chooseAllocator(allocatorType))
90 .childHandler(new HttpNativeServerInitializer(httpRequestFuture));
91
92 Channel channel = b.bind(0).sync().channel();
93 System.err.println("Server started, will shutdown now.");
94
95 Channel httpClient = new HttpNativeClient(
96 ((InetSocketAddress) channel.localAddress()).getPort(),
97 group, chooseChannelClass(ioType)
98 ).initClient();
99 DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/hello");
100
101 httpClient.writeAndFlush(request).sync();
102
103 httpRequestFuture.get();
104
105 channel.close().sync();
106 httpClient.close().sync();
107 serverStartSucess = true;
108 } finally {
109 group.shutdownGracefully();
110 }
111 return serverStartSucess;
112 }
113
114 public static IoHandlerFactory chooseFactory(TransportType ioType) {
115 if (ioType == TransportType.EPOLL) {
116 return EpollIoHandler.newFactory();
117 }
118
119 if (ioType == TransportType.IO_URING) {
120 IoUringIoHandlerConfig config = new IoUringIoHandlerConfig();
121 if (IoUring.isRegisterBufferRingSupported()) {
122 config.setBufferRingConfig(
123 IoUringBufferRingConfig.builder()
124 .bufferGroupId((short) 0)
125 .bufferRingSize((short) 16)
126 .batchSize(16)
127 .allocator(new IoUringFixedBufferRingAllocator(1024))
128 .batchAllocation(false)
129 .build()
130 );
131 }
132
133 return IoUringIoHandler.newFactory(config);
134 }
135
136 return NioIoHandler.newFactory();
137 }
138
139 public static ByteBufAllocator chooseAllocator(AllocatorType allocatorType) {
140 switch (allocatorType) {
141 case POOLED : return PooledByteBufAllocator.DEFAULT;
142 case UNPOOLED : return UnpooledByteBufAllocator.DEFAULT;
143 case ADAPTIVE: return new AdaptiveByteBufAllocator();
144 default: return PooledByteBufAllocator.DEFAULT;
145 }
146 }
147
148 public static Class<? extends ServerSocketChannel> chooseServerChannelClass(TransportType ioType) {
149 if (ioType == TransportType.EPOLL) {
150 return EpollServerSocketChannel.class;
151 }
152
153 if (ioType == TransportType.IO_URING) {
154 return IoUringServerSocketChannel.class;
155 }
156
157 return NioServerSocketChannel.class;
158 }
159
160 public static Class<? extends Channel> chooseChannelClass(TransportType ioType) {
161 if (ioType == TransportType.EPOLL) {
162 return EpollSocketChannel.class;
163 }
164
165 if (ioType == TransportType.IO_URING) {
166 return IoUringSocketChannel.class;
167 }
168
169 return NioSocketChannel.class;
170 }
171
172 enum TransportType {
173 NIO,
174 EPOLL,
175 IO_URING,
176 }
177
178 enum AllocatorType {
179 POOLED,
180 UNPOOLED,
181 ADAPTIVE
182 }
183 }