XRebel shows a default session size of 25.3 MB using the first set of code below. The session drops below 50kb if I use the second set instead.
I have this “sw.js” code as part of the [Progressive Web App (PWA)]
(https://vaadin.com/pwa/build). XRebel seems to isolate it to MavenSession inside AtmosphereFramework’s ShutdownHook. I use Jetty for production.
Why does removing that code reduce the session size so drastically?
Does this large size only exist in production? I’m trying to optimize for scale.
This code causes session size: 25.3 MB
@WebServlet(urlPatterns = "/*", name = "LoginUIServlet", asyncSupported = true)
@VaadinServletConfiguration(closeIdleSessions = true, ui = LoginUI.class, productionMode = false)
public static class LoginUIServlet extends VaadinServlet {
@Override
protected void servletInitialized() throws ServletException {
super.servletInitialized();
HeaderTagHandler.init(getService());
getService().addSessionInitListener(new SessionInitListener() {
@Override
public void sessionInit(SessionInitEvent event) {
event.getSession().addRequestHandler(new RequestHandler() {
@Override
public boolean handleRequest(VaadinSession session, VaadinRequest request,
VaadinResponse response) throws IOException {
String pathInfo = request.getPathInfo();
InputStream in = null;
if (pathInfo.endsWith("sw.js")) {
response.setContentType("application/javascript");
in = getClass().getResourceAsStream("/sw.js");
}
if (in != null) {
OutputStream out = response.getOutputStream();
IOUtils.copy(in, out);
in.close();
out.close();
return true;
} else {
return false;
}
}
});
}
});
}
}
The memory usage in your case is attributed by the size of “sw.js” and implementation of actual InputStream and OutputStream used. In this case InputStream and OutputStream are inherited from standard Servlet implementation, you could check discussion here, which is somewhat related
"For example, copy(InputStream, OutputStream) calls copyLarge(InputStream, OutputStream) which calls copy(InputStream, OutputStream, int) which creates the buffer and calls copyLarge(InputStream, OutputStream, byte).
Applications can re-use buffers by using the underlying methods directly. This may improve performance for applications that need to do a lot of copying.
Wherever possible, the methods in this class do not flush or close the stream. This is to avoid making non-portable assumptions about the streams’ origin and further use. Thus the caller is still responsible for closing streams after use."
What are you suggesting I do differently than what I’m trying? My code shows I’m already closing both the InputStream and OutputStream, and flushing the OutputStream beforehand. Still a 25 MB session.
2 Theories:
I noticed that this code:
String pathInfo = request.getPathInfo();
InputStream in = null;
System.out.println("path info: "+pathInfo);
if (pathInfo.endsWith("sw.js")) {
response.setHeader("Content-Length", String.valueOf(new File("/sw.js").length()));
response.setContentType("application/javascript");
in = getClass().getResourceAsStream("/sw.js");
System.out.println("got here");
}