Tuesday, November 25, 2008

Protobuf vs Spring RPC

Did some RPC tests over the wire and got some interesting results. Hope that someone could do something similar and verify.
I run three RPC client/server combination (see links to source code):

  1. Protobuf as the protocol over a simple TCP/IP client/server java sockets.
  2. Protobuf as the protocol over a HTTP where the client is using Apache HTTP client (reusing connection), and the server part is a servlet in a War on Jetty v6. The server side (protowar) implementation is very basic and ment only for benchmarking.
  3. Spring RPC, the war container is Jetty v6. Not posting the source code for this one, but its basically the same as in the protobuf example, using java serialization and spring.
I did a warmup for each client service combination to get the JIT going, and took the minimum of many iterations to try and dodge the GC. All the test I run on the same single (localhost) machine which is a MacBook Pro with 4GB of RAM and Intel Core 2 Duo. Surely its not a falst machine and you'll get much better results on a decent server, still, I would expect the relationships will stay the same. The results:
  1. protobuf on plain socket: 0.228 milli/roundtrip
  2. protobuf on HTTP: 2.08 milli/roundtrip
  3. Spring/RPC: 106.8 milli/roundtrip
Note that the chart below is in logarithmic scale!
I.e. you loose over an order of magnitude by using HTTP. But say you would like to keep it around and use the benefits of web containers, HTTP VIPs etc, then a milli (less on a real server) might be worth it. But jumping to Spring/RPC, that will cost you. Sure, you have tons of benefits there, just make sure you know the tradeof.

2 comments:

Markus Kohler November 25, 2008 at 4:01 AM  

Interesting results!
I wonder why Spring is really that slow.
I didn't look at the source code in detail, but it seems you send arrays around.
What is the size of those arrays?

You may also improve your client a little bit.

I think MediaServer.getDescriptor().findMethodByName("updateMedia")
could be moved out of the loop.

Regards,
Markus

Eishay Smith November 25, 2008 at 8:21 AM  

@Markus Thanks for the comment. We should retrieve the method descriptor in the loop itself since I read the method identifier a line before.

int index = dis.readInt();
MethodDescriptor method = getDescriptor().getMethods().get(index);

This lookup is fast since we are getting an object using index from an array list -> O(1). Actually, in order to fully mimic Spring/RPC I should also do a service lookup using the service ID (also an integer). I don't think it would have matter too much since it would also be an indexed retrieval from an array list.


The size of the message array is about 200 bytes. See Protobuf with option optimize for SPEED for more info.

Creative Commons License This work by Eishay Smith is licensed under a Creative Commons Attribution 3.0 Unported License.