For such a small message, you may find that if you use flat arrays rather than stream I/O, it may be significantly faster. That is, when serializing, call toByteArray() and then write the array to the stream, and on the parsing end, read the array first, then call parseFrom() on that. Admittedly, the stream I/O methods should be doing this automatically if it is faster.
On Tue, Aug 18, 2009 at 7:43 AM, Tai <[email protected]> wrote: > > What I am measuring in writeObject() and readObject() is: > > 1) For PB I only measure the writeDelimitedTo() and parseDelimitedFrom > public class PojoUsingPB extends AbstractPojo implements Serializable > { > ... > private void writeObject(java.io.ObjectOutputStream out) throws > IOException { > ... > long start = System.nanoTime(); > message.writeDelimitedTo(out); > long end = System.nanoTime(); > ... > } > > private void readObject(java.io.ObjectInputStream in) > throws ClassNotFoundException, IOException { > long start = System.nanoTime(); > PojoMessage.Pojo message = PojoMessage.Pojo.parseDelimitedFrom > (in); > long end = System.nanoTime(); > ... > > 2) In Java I measure the ObjectOutputStream.writeObject() and > ObjectInputStream.readObject(): > public class PojoUsingJava extends AbstractPojo implements > Serializable { > ... > private void writeObject(java.io.ObjectOutputStream out) throws > IOException { > long start = System.nanoTime(); > out.writeObject(key); > out.writeObject(value); > out.writeBoolean(someBoolean); > long end = System.nanoTime(); > ... > } > > private void readObject(java.io.ObjectInputStream in) > throws ClassNotFoundException, IOException { > long start = System.nanoTime(); > key = (String) in.readObject(); > value = (String) in.readObject(); > someBoolean = in.readBoolean(); > long end = System.nanoTime(); > ... > > I don't know where I could have done something wrong. The results I am > getting is: > Duration using Java > Protocol Buffers > Average remote time = 111309 > 122173 nanosecs > Average serialization time = 3609 > 6586 nanosecs > Average de-serialization time = 3533 > 9287 nanosecs > > Based on that PB seems to be slower and I am not coming to the same > conclusion as stated in other performance tests?! > > Tai > > > > On Aug 17, 11:24 pm, Kenton Varda <[email protected]> wrote: > > A message with three primitive fields should only take a couple hundred > > nanoseconds to parse or serialize, unless the strings are *huge*. I have > to > > believe that something is wrong with the setup. > > > > On Mon, Aug 17, 2009 at 1:53 PM, Tai <[email protected]> wrote: > > > > > I have now also tried parseDelimitedFrom() and writeDelimitedTo. The > > > performance difference is still by a factor of almost 2: > > > > > Average Java time: 154333 nanosecs > > > Average PB time: 293566 nanosecs > > > > > Average Java time: 149934 nanosecs > > > Average PB time: 275076 nanosecs > > > > > I will try with a bigger message but I doubt that PB will get any > > > close to Java's total performance (serialization, deserialization and > > > object creation). > > > > > I was hoping to give our RMI environment a boost but I doesn't look > > > like this. I will give it another chance. > > > > > Tai > > > > > On 17 Aug., 22:07, Kenton Varda <[email protected]> wrote: > > > > Oops, I missed it when skimming. > > > > > > > PojoMessage.Pojo message = PojoMessage.Pojo.parseFrom(in); > > > > > > That line won't work. Protocol buffers are not self-delimiting, so > > > > parseFrom() -- if it succeeds -- always reads the *entire* input. > You > > > > should use parseDelimitedFrom() instead, and use writeDelimitedTo() > on > > > the > > > > sending side. > > > > > > BTW, with such a small message, the cost of serializing and parsing > the > > > > message is going to be extremely small compared to the cost of the > RPC > > > > system, network time, etc. I'd be pretty surprised if there is any > > > > significant difference between the two approaches. > > > > > > On Mon, Aug 17, 2009 at 12:48 PM, Tai <[email protected]> > wrote: > > > > > > > I am using 2.1.0 and as shown above the proto file uses option > > > > > optimize_for = SPEED; > > > > > > > On Aug 17, 8:56 pm, Kenton Varda <[email protected]> wrote: > > > > > > What version of protocol buffers are you using? If it's 2.0.3 or > > > > > previous > > > > > > then you need to put this line in your proto files: > > > > > > option optimize_for = SPEED; > > > > > > > > In 2.1.0 and up, this is the default. > > > > > > > > On Mon, Aug 17, 2009 at 10:29 AM, Tai <[email protected]> > > > wrote: > > > > > > > > > Hi, > > > > > > > > > I did some simple test to compare Java vs. ProtocolBuffers. I > know > > > > > > > that there is already a very verbose benchmark measuring > > > > > > > serialization, object creation and de-serialization here: > > > > >http://www.eishay.com/2009/03/more-on-benchmarking-java-serialization. > > > > > .. > > > > > > > > > But when using RMI I am getting a total time where PB is slower > > > than > > > > > > > Java. My performance test measures the total time when passing > a > > > Pojo > > > > > > > from a client to a remote agent. The results I get when running > the > > > > > > > tests twice are: > > > > > > > Average Java time: 147421 nanosecs > > > > > > > Average PB time: 281617 nanosecs (factor 1.91 slower) > > > > > > > > > Average Java time: 232446 nanosecs > > > > > > > Average PB time: 467485 nanosecs (factor 2.01 slower) > > > > > > > > > I was expecting PB to be faster than Java?! But this seems to > be > > > > > > > wrong. > > > > > > > > > My classes are (unfortunately I cannot attach to the source / > you > > > can > > > > > > > email me if you want a zip): > > > > > > > > > The rmi interface for the agent server: > > > > > > > ========================================================= > > > > > > > package test.protocolbuffers; > > > > > > > > > import java.rmi.Remote; > > > > > > > import java.rmi.RemoteException; > > > > > > > > > public interface IRemoteAgent extends Remote { > > > > > > > > > long doSomething(long start, Object pojo) throws > > > RemoteException; > > > > > > > > > } > > > > > > > ========================================================= > > > > > > > > > The server agent implementing the interface > > > > > > > ========================================================= > > > > > > > package test.protocolbuffers; > > > > > > > > > import java.rmi.RemoteException; > > > > > > > import java.rmi.registry.LocateRegistry; > > > > > > > import java.rmi.registry.Registry; > > > > > > > import java.rmi.server.UnicastRemoteObject; > > > > > > > > > public class RemoteAgent implements IRemoteAgent { > > > > > > > > > public RemoteAgent() { > > > > > > > } > > > > > > > > > public static void main(String[] args) throws Exception { > > > > > > > RemoteAgent agent = new RemoteAgent(); > > > > > > > String name = "RemoteAgent1"; > > > > > > > UnicastRemoteObject.exportObject(agent, 0); > > > > > > > Registry registry; > > > > > > > try { > > > > > > > registry = LocateRegistry.createRegistry(1099); > > > > > > > } catch (Exception e) { > > > > > > > registry = LocateRegistry.getRegistry(); > > > > > > > } > > > > > > > registry.rebind(name, agent); > > > > > > > System.out.println(name + " bound."); > > > > > > > > > } > > > > > > > > > public long doSomething(long start, Object pojo) throws > > > > > > > RemoteException { > > > > > > > long end = System.nanoTime(); > > > > > > > return end - start; > > > > > > > } > > > > > > > } > > > > > > > ========================================================= > > > > > > > > > The Java POJO for measuring the using standard Java > serialization: > > > > > > > ========================================================= > > > > > > > package test.protocolbuffers; > > > > > > > > > import java.io.Serializable; > > > > > > > > > public class PojoUsingJava implements Serializable { > > > > > > > private String key; > > > > > > > private String value; > > > > > > > private boolean someBoolean; > > > > > > > > > public PojoUsingJava(String key, String value, boolean > > > > > > > someBoolean) { > > > > > > > this.key = key; > > > > > > > this.value = value; > > > > > > > this.someBoolean = someBoolean; > > > > > > > } > > > > > > > > > } > > > > > > > ========================================================= > > > > > > > > > The PB Pojo: > > > > > > > ========================================================= > > > > > > > package test.protocolbuffers; > > > > > > > > > import java.io.IOException; > > > > > > > import java.io.Serializable; > > > > > > > import test.protocolbuffers.PojoMessage.Pojo.Builder; > > > > > > > > > public class PojoUsingPB implements Serializable { > > > > > > > private String key; > > > > > > > private String value; > > > > > > > private boolean someBoolean; > > > > > > > > > public PojoUsingPB(String key, String value, boolean > > > someBoolean) > > > > > > > { > > > > > > > this.key = key; > > > > > > > this.value = value; > > > > > > > this.someBoolean = someBoolean; > > > > > > > } > > > > > > > > > private void writeObject(java.io.ObjectOutputStream out) > throws > > > > > > > IOException { > > > > > > > Builder builder = PojoMessage.Pojo.newBuilder(); > > > > > > > builder.setKey(key); > > > > > > > builder.setValue(value); > > > > > > > builder.setSomeBoolean(someBoolean); > > > > > > > PojoMessage.Pojo message = builder.build(); > > > > > > > message.writeTo(out); > > > > > > > } > > > > > > > > > private void readObject(java.io.ObjectInputStream in) > > > > > > > throws ClassNotFoundException, IOException { > > > > > > > PojoMessage.Pojo message = > PojoMessage.Pojo.parseFrom(in); > > > > > > > key = message.getKey(); > > > > > > > value = message.getValue(); > > > > > > > someBoolean = message.getSomeBoolean(); > > > > > > > } > > > > > > > > > } > > > > > > > ========================================================= > > > > > > > > > The proto file being used in the PB Pojo: > > > > > > > ========================================================= > > > > > > > package test.protocolbuffers; > > > > > > > > > option optimize_for = SPEED; > > > > > > > > > message Pojo { > > > > > > > > > optional string key = 1; > > > > > > > optional string value = 2; > > > > > > > optional bool someBoolean = 3; > > > > > > > }========================================================= > > > > > > > > > The test class for measuring the remote calls using Java and > PB: > > > > > > > ========================================================= > > > > > > > package test.protocolbuffers; > > > > > > > > > import java.rmi.registry.LocateRegistry; > > > > > > > import java.rmi.registry.Registry; > > > > > > > > > public class RemoteProtoPerfTest { > > > > > > > > > public static void main(String[] args) throws Exception { > > > > > > > //get the remote agent > > > > > > > Registry registry = LocateRegistry.getRegistry(1099); > > > > > > > IRemoteAgent remoteAgent = (IRemoteAgent) > registry.lookup > > > > > > > ("RemoteAgent1"); > > > > > > > // warm up > > > > > > > for (int i = 0; i < 100; i++) { > > > > > > > remoteAgent.doSomething(System.nanoTime(), > "warmup"); > > > > > > > } > > > > > > > int calls = 1000; > > > > > > > > > //measure the total time (serialization, network > > > > > > > transportation, deserialization) > > > > > > > //using java serialization > > > > > > > long totalJavaDuration = 0; > > > > > > > PojoUsingJava pojoUsingJava = new PojoUsingJava("key", > > > > > > > "value", false); > > > > > > > for (int i = 0; i < calls; i++) { > > > > > > > if ( i % 200 == 0) { > > > > > > > System.out.println("Loop: " + i); > > > > > > > } > > > > > > > totalJavaDuration += remoteAgent.doSomething > > > > > > > (System.nanoTime(), pojoUsingJava); > > > > > > > } > > > > > > > totalJavaDuration /= calls; > > > > > > > System.out.println("Average Java time: " + > totalJavaDuration > > > + > > > > > > > " nanosecs"); > > > > > > > > > //measure the total time (serialization, network > > > > > > > transportation, deserialization) > > > > > > > //using Protocol Buffers > > > > > > > long totalPbDuration = 0; > > > > > > > PojoUsingPB pojoUsingPB = new PojoUsingPB("key", > "value", > > > > > > > false); > > > > > > > for (int i = 0; i < calls; i++) { > > > > > > > if ( i % 200 == 0) { > > > > ... > > > > read more ยป > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/protobuf?hl=en -~----------~----~----~----~------~----~------~--~---
