My latest web project  is setting up a real estate site in Indonesia with GWT. While the number of internet users grow at an astonishing rate, much of the internet connectivity is achieved through slow dial ups or mobile connections. Thus the primary technical goal was keeping network payload to a minimum. GWT RPC seemed from the beginning a natural winner, not only because of the excellent Java integration but also because of it’s much more compact format when compared to Json or XML .
And the best part is: it turns out that this very good starting point can be further optimised.
Using GET over POST
The Yahoo performance team has put together a worthwhile read  about website performance. One of their finding was that POST requests are transmitted over the network with more packets than GET requests. This is not only slower, but increases on a bad network connection the chance of a transmission retry due to lost packets. I’ve covered this particular optimization (with code examples!) in  already.
A further positive side effect is that GET requests are cacheable, provided that your webserver is returning the correct HTTP headers (i.e. Cache-Control, Expires etc). The Bazarooma network layer makes good and thorough use of this caching technique which, when combined with a reverse web proxy such as Varnish considerably lightens server load.
Removing type names
1. Inherit it in the module xml:
2. Instruct the server side payload generator to elide typenames. Since Bazarooma is using GETs for RPC, we were running a custom RPC generator anyway, so this was a one-liner:
RPC.encodeResponseForSuccess(serviceMethod, methodArgument, policy, AbstractSerializationStream.FLAG_ELIDE_TYPE_NAMES);
Please note that use of a serialization policy is absolutely a must. Also in our case, the production deployment will occasionally and without any apparent reason refuse RPC requests with an exception complaining about type name elision. The solution to this turns out to be as annoying as trivial: redo the entire deployment.
Variable packing means representing several members with a single variable, i.e. boolean values as bits in an integer. This requires a change in the implementation of the domain objects (or data transfer objects) used, which should not be much of a problem as the interface doesn’t change.
For example, this:
return (bitmap & 1)!=0;
return (bitmap & 2)!=0;
Please note that in our case this reduced the payload by a marginal 5% after GZipping while increasing the deserialization time on the client (FF 3.6) by 15%.
GWT’s RemoteServiceServlet performs standard Gzip compression on the RPC payload by using standard JDK settings. We disabled RPC compression and instead performed our own Gzip compression (Java’s GzipOutputStream) with bigger buffers and higher compression settings which reduced payload size on average by 5%. Please note that the compression time will most likely drastically rise in this case (I don’t have any numbers though), thus not always making it a clear win with regard to server load.
The idea behind batching is to group multiple logical RPC requests into one physical payload and HTTP request which results in one physical payload and HTTP response. There are frameworks that take care of this , we wrote our own (for no particular reason, it was just too easy to do 🙂
Batching allowed us even to eliminate unnecessary requests, for instance when a user was clicking fast through search results, not really spending time on them. A naive implementation would have requested all results from the server, while batching allowed us to send only the last, valid command to the server.
[Update 31.03.2011] As Gal Dolber points out , batching strongly inhibits code splitting/deferred loading.
[Update 31.03.2011] Removing HTTP headers
If you’ve inspected an RPC request with Firebug (or similar), you’ll notice that there are many request headers which are not really usefull, such as the host name, user-agent, encodings etc. I tried to remove these by replacing XmlHttpRequest (you can’t meaningfully extend it, need to replace it in the GWT jar) but it turns out that most headers are defaulted by the browser and cannot be removed. With Firefox, for example, it turns out that only the User-Agent header can be removed.
You may also want to remove the custom X-GWT-* headers, but this will most certainly cause RemoteServiceServlet to complain about them missing. I solved this re-introducing these header on the server side with a custom filter (see GET vs POST earlier)
 Internet users by country
 GWT RPC protocol
 Yahoo performance blog
 GWT RPC over HTTP GET
 Obfuscating GWT RPC type names
 Batching GWT RPC requests with GWT-Dispatch
 Discussion on the GWT list about batching