To start off, I created a simple test page, inserted an h1, then a <% response.flushBuffer %>, then a function call that triggers a breakpoint. I would expect the server to send everything up to the h1 down to the browser, and then not send the rest of the page until I resumed the breakpoint. In practice, though, nothing is sent until after I resume the breakpoint, and the whole page is sent down at once.
I read that this might be due to some sort of buffer size in Tomcat or JSP, so I inserted 20kb worth of padding data before the h1, but still I see the same behavior: nothing is sent, and then at the end of the page everything is sent. I also read that this might just be due to the browser not rendering data until it has "enough", but I fired up wireshark and sure enough nothing is being sent back at the HTTP level until after I resume the breakpoint and the whole page is rendered.
So how can I make flushing actually flush part of the response down to the client prematurely? (I'm using Struts and JSP, with Tomcat as the webserver.)
Hi William, yes, I'm using Eclipse. I'm calling a Java function where I have a breakpoint set.
Debraj, the autoFlush attribute is not what I'm worried about here. I'm trying to flush at a specific location: right after I render the header. My JSP basically looks like this:
I would like it to render everything up to that h1, send it down to the client, and then send the rest of the page down to the client after I've resumed the breakpoint.
You can see similar behavior set up for perf reasons on high traffic sites like search engines. If you artificially slow your connection, use a packet sniffer, or even just pay close attention when doing a query on Google, you'll notice that they send everything at the top of the page up to the search box down first, and then the results follow a bit after that. This is done so that the client's browser can begin rendering the page as soon as possible, increasing overall performance by quite a bit.
The level of control you seek is not possible. There are many factors controlling when the browser will receive and display information, most of which you have no control over. The time you are spending on this would be better spent solving the real problems.
If your DB queries are taking too long, that's where profiling and improvement should be targeted.
Also note that putting Java code in a JSP is a long-discredited practice that should have stopped 9 years ago. Your code will be cleaner, and easier to profile if it is properly placed inside Java classes.
If it proves impossible to tune the queries to within acceptable limits, there are a number of alternative approaches you can use:
You could spawn the lengthy process off as a background thread and return control to the browser. Give the user a way to check back later to see if the processing is completed and check its status.
Send the user to a page that uses Ajax to set off the lengthy process behind the scenes. The page can explain what's going on, and if possible even provide a progress bar if feasible.
Hi Bear, I apologize that I didn't make this more clear: what I'm trying to do here is not the first step I've taken to improve our site's performance. I've already got whole-page profiling set up and have heavily optimized our DB, since it was the initial bottleneck as you've suggested. I've already brought end-to-end latency down by 70%, and am now at the point where client-side performance has more room for improvement than server-side performance.
Are you sure the level of control I seek isn't possible? It would seem that this type of control is exactly what response.flushBuffer was designed to do. I've worked on several big sites making similar improvements (unfortunately, none of them to-date have used Java/JSP), and can assure you this is a legitimate technique with significant performance improvement potential. See here for a somewhat authoritative source: http://developer.yahoo.com/performance/rules.html#flush
Every other web development framework I've tried this with (PHP, ASP.NET, Rails, etc.) have supported sending parts of the page down before the rest of the page like this, so I would be shocked if JSP/Struts/Tomcat didn't.
(Also, I understand and agree that using Java inside JSP like you mentioned is terrible. I was merely using it for brevity in my example, and I promise that the final implementation will avoid any such atrocity. )