The postings on this site are the contributor's and don’t necessarily represent IBM’s positions, strategies or opinions.
March 14th, 2010 Alex Moffat Posted in AJAX, GWT | No Comments »
Tools like Page Speed or YSlow are great for analyzing page load performance. You can use JavaScript profiling or simple timing statements to find problem areas in your code at runtime, bearing in mind of course that its more often than not DOM manipulation rather than pure JavaScript execution that is slowing you down. One other piece of data that is very useful is the roundtrip time for your requests to the server. Knowing the average roundtrip time and the distribution of times helps you decide how to chunk requests and sets a lower limit on the possible response time for a request. You can use the information when testing to help simulate the experience users at remote location will see, and knowing which users have slow connections or are experiencing network problems helps resolve problems.
So how do you measure roundtrip time? There are two parts to this, the actual time measurement and getting the data back to the server. The measurement is done using the GWT Lightweight Metrics System. This provides timing points just before an RPC request is sent and just after the response is received. Take a look at the GWT RPC Event Diagram in the LightweightMetricsDesign document. I’m already using lightweight metrics as part of my episodes like system to record timings during page load. Recording RPC timings is just a case of adding a couple of new functions to handle events from the RPC subsystem. If the subSystem field on an event has the value rpc then this function is called.
// Deal with events from the GWT rpc system.
DOINGS.gwtRpcEvent = function (e) {
if ("requestSent" == e.type) {
DOINGS.rpcRequestsOutstanding[e.evtGroup] = e.millis;
return;
}
if ("responseReceived" == e.type) {
if (DOINGS.rpcRequestsOutstanding[e.evtGroup]) {
var elap = e.millis - DOINGS.rpcRequestsOutstanding[e.evtGroup];
DOINGS.mostRecentRequest = {id: e.evtGroup, millis: elap};
delete DOINGS.rpcRequestsOutstanding[e.evtGroup];
}
return;
}
};
I just keep track of the elapsed time for the most recent request.
For detailed analysis I also want to be able to subtract the server processing time from the total roundtrip time so that I can calculate just the network time. As each request is processed by the server the processing time can be recorded. The roundtrip time isn’t known yet though, the client can only calculate this when the response gets back to the client. So, the sequence of events must be something like
To do this I have to be able to uniquely identify a client request, that is provide a value for N. This is done with two value, a unique identifier for a client session, and a unique identifier for a request within a session. The unique identifier for each request is already provided by the lightweight metrics system in the evtGroup field of the metrics event. I use an existing client side unique id generation component to assign an id to each client session.
Finally the data must be sent to the server where it can be recorded. This is done in a header added to the http request by a subclass of RpcRequestBuilder.
protected void doSetRequestId(RequestBuilder rb, int id) {
RpcCallTiming lastCall = Doings.getMostRecentCallTimings();
if (lastCall != null && lastCall.getId() != -1) {
rb.setHeader(TIMINGS_HEADER, (clientSessionId == null ? "" : "i" + clientSessionId +
",") + "r" + id +
",l" + lastCall.getId() + ",t" + lastCall.getMillis());
}
}
Using a request builder and an HTTP header means I don’t have to modify all of the individual RPC calls. It’s interesting to consider whether adding this sort of information to an overall RPC framework is a good idea. I tend to think not, building that sort of structure in from the start can distract from getting actual productive features done.
Leave a Reply