Skip to content

Commit 22ef1d6

Browse files
committed
Performance improvements in Jersey by initializing the ApplicationHandler in the filter constructor (absorbed by Lambda) and not in the filter init method
1 parent b3089e3 commit 22ef1d6

File tree

3 files changed

+79
-6
lines changed

3 files changed

+79
-6
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.amazonaws.serverless.proxy.internal.testutils;
2+
3+
4+
import java.util.LinkedHashMap;
5+
import java.util.Map;
6+
7+
8+
public final class Timer {
9+
private volatile static Map<String, TimerInfo> timers = new LinkedHashMap<>();
10+
11+
public static void start(String timerName) {
12+
timers.put(timerName, new TimerInfo(System.currentTimeMillis()));
13+
}
14+
15+
public static long stop(String timerName) {
16+
TimerInfo info = timers.get(timerName);
17+
if (info == null) {
18+
throw new IllegalArgumentException("Could not find timer " + timerName);
19+
}
20+
21+
long stopTime = System.currentTimeMillis();
22+
info.stop(stopTime);
23+
24+
return stopTime;
25+
}
26+
27+
28+
public static Map<String, TimerInfo> getTimers() {
29+
return timers;
30+
}
31+
32+
public static TimerInfo getTimer(String timerName) {
33+
return timers.get(timerName);
34+
}
35+
36+
private static class TimerInfo {
37+
private long startTime;
38+
private long stopTime;
39+
private long duration;
40+
41+
public TimerInfo(long start) {
42+
startTime = start;
43+
}
44+
45+
public void stop(long stop) {
46+
stopTime = stop;
47+
duration = stopTime - startTime;
48+
}
49+
50+
public long getStartTime() {
51+
return startTime;
52+
}
53+
54+
public long getStopTime() {
55+
return stopTime;
56+
}
57+
58+
59+
public long getDuration() {
60+
return duration;
61+
}
62+
}
63+
}

aws-serverless-java-container-jersey/src/main/java/com/amazonaws/serverless/proxy/jersey/JerseyHandlerFilter.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.amazonaws.serverless.proxy.jersey;
22

33

4-
import com.amazonaws.serverless.exceptions.InvalidRequestEventException;
54
import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest;
5+
import com.amazonaws.serverless.proxy.internal.testutils.Timer;
66

77
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
88
import org.glassfish.jersey.internal.MapPropertiesDelegate;
@@ -49,22 +49,25 @@ public class JerseyHandlerFilter implements Filter, Container {
4949
private Logger log = LoggerFactory.getLogger(JerseyHandlerFilter.class);
5050

5151
public JerseyHandlerFilter(Application jaxApplication) {
52+
Timer.start("JERSEY_FILTER_INIT");
5253
app = jaxApplication;
54+
55+
jersey = new ApplicationHandler(app);
56+
jersey.onStartup(this);
57+
Timer.stop("JERSEY_FILTER_INIT");
5358
}
5459

5560
@Override
5661
public void init(FilterConfig filterConfig)
5762
throws ServletException {
5863
log.info("Initialize Jersey application handler");
59-
jersey = new ApplicationHandler(app);
60-
jersey.onStartup(this);
6164
}
6265

6366

6467
@Override
6568
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
6669
throws IOException, ServletException {
67-
log.debug("Called Jersey filter");
70+
Timer.start("JERSEY_FILTER_DOFILTER");
6871
// we use a latch to make the processing inside Jersey synchronous
6972
CountDownLatch jerseyLatch = new CountDownLatch(1);
7073

@@ -80,7 +83,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
8083
log.error("Interrupted while processing request", e);
8184
throw new InternalServerErrorException(e);
8285
}
83-
86+
Timer.stop("JERSEY_FILTER_DOFILTER");
8487
filterChain.doFilter(servletRequest, servletResponse);
8588
}
8689

aws-serverless-java-container-jersey/src/main/java/com/amazonaws/serverless/proxy/jersey/JerseyLambdaContainerHandler.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest;
2626
import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequestReader;
2727
import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter;
28+
import com.amazonaws.serverless.proxy.internal.testutils.Timer;
2829
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
2930
import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
3031

@@ -120,11 +121,13 @@ public JerseyLambdaContainerHandler(RequestReader<RequestType, AwsProxyHttpServl
120121
SecurityContextWriter<RequestType> securityContextWriter,
121122
ExceptionHandler<ResponseType> exceptionHandler,
122123
Application jaxRsApplication) {
123-
super(requestReader, responseWriter, securityContextWriter, exceptionHandler);
124124

125+
super(requestReader, responseWriter, securityContextWriter, exceptionHandler);
126+
Timer.start("JERSEY_START_TIMER");
125127
this.jaxRsApplication = jaxRsApplication;
126128
this.initialized = false;
127129
this.jerseyFilter = new JerseyHandlerFilter(this.jaxRsApplication);
130+
Timer.stop("JERSEY_START_TIMER");
128131
}
129132

130133
//-------------------------------------------------------------
@@ -140,10 +143,12 @@ protected AwsHttpServletResponse getContainerResponse(AwsProxyHttpServletRequest
140143
protected void handleRequest(AwsProxyHttpServletRequest httpServletRequest, AwsHttpServletResponse httpServletResponse, Context lambdaContext)
141144
throws Exception {
142145

146+
Timer.start("JERSEY_HANDLE_REQUEST");
143147
// this method of the AwsLambdaServletContainerHandler sets the request context
144148
super.handleRequest(httpServletRequest, httpServletResponse, lambdaContext);
145149

146150
if (!initialized) {
151+
Timer.start("JERSEY_INITIALIZATION");
147152
// call the onStartup event if set to give developers a chance to set filters in the context
148153
if (startupHandler != null) {
149154
startupHandler.onStartup(getServletContext());
@@ -154,10 +159,12 @@ protected void handleRequest(AwsProxyHttpServletRequest httpServletRequest, AwsH
154159
jerseyFilterReg.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
155160

156161
initialized = true;
162+
Timer.stop("JERSEY_INITIALIZATION");
157163
}
158164

159165
httpServletRequest.setServletContext(getServletContext());
160166

161167
doFilter(httpServletRequest, httpServletResponse, null);
168+
Timer.stop("JERSEY_HANDLE_REQUEST");
162169
}
163170
}

0 commit comments

Comments
 (0)