skip to main | skip to sidebar

Thursday, March 24, 2011

Ruby and Protocol Buffers, Take One

At work, we're moving from XML to protocol buffers. While we're mostly a Java shop, the operations/sysadmin team I'm on does a lot of Ruby. I was interested in how we might use the same technology for some of our stuff. After a bit of looking, I found two libraries that looked mature enough to investigate:

ruby-protobuf, by MATSUYAMA Kengo (@macks_jp), was straightforward to install and use. It has a good online tutorial and the redme has all I needed to get started.
ruby-protocol-buffers, by Brian Palmer was also easy to install and use. It seems a bit lacking in the online documentation, but does have some examples to follow. (If Brian's name rings a bell, it might be because I interviewed him some time ago about winning a programming contest sponsored by Mozy's former incarnation.)
I started out with a very simple proto file:

package bench;
message Person {
 required string name = 1;
 required int32 id = 2;
 optional string email = 3;
}

I compiled this with rprotoc for ruby-protobuf and with ruby-protoc for ruby-protocol-buffers. This generated the following (which I edited lightly). For ruby-protof:

### Generated by rprotoc. DO NOT EDIT!
### <proto file: bench.proto>
# package bench;
#
# message Person {
#  required string name = 1;
#  required int32 id = 2;
#  optional string email = 3;
# }
require 'protobuf/message/message'
require 'protobuf/message/enum'
require 'protobuf/message/service'
require 'protobuf/message/extend'
module Bench1
 class Person1 < ::Protobuf::Message
  defined_in __FILE__
  required :string, :name, 1
  required :int32, :id, 2
  optional :string, :email, 3
 end
end
for ruby-protocol-buffer
#!/usr/bin/env ruby
# Generated by the protocol buffer compiler. DO NOT EDIT!
require 'protocol_buffers'
# Reload support
Object.__send__(:remove_const, :Bench2) if defined?(Bench2)
module Bench2
 # forward declarations
 class Person2 < ::ProtocolBuffers::Message; end
 class Person2 < ::ProtocolBuffers::Message
  required :string, :name, 1
  required :int32, :id, 2
  optional :string, :email, 3
  gen_methods! # new fields ignored after this point
 end
end

Then I pulled out the statistical benchmarking I wrote about a while ago (Since no one else has taken the bait, maybe I should bundle up a gem for that.). Instead of quoting the whole thing at you, here are the pertinent loops. For ruby-protobuf:

msg = Bench1::Person1.new(:name => idx.to_s,
             :id => idx,
             :email => idx.to_s)
msg_str = msg.serialize_to_string
msg == msg.parse_from_string(msg_str)

for ruby-protocol-buffer:

msg = Bench2::Person2.new(:name => idx.to_s,
             :id => idx,
             :email => idx.to_s)
 msg == Bench2::Person2.parse(msg.to_s)
And here are the results:

$ rvm 1.9.2
$ ruby -v
ruby 1.9.2p0 (2010年08月18日 revision 29036) [i686-linux]
$ time ruby ProtoBufBench
testing ruby-protobuff against ruby-protocol-buffer
The deviation in the deltas was 0.021731
The mean delta was 0.198301
max = 0.241761921640842 :: min = 0.154839326146633
ruby-protocol-buffer was better
real1m50.672s
user1m50.599s
sys0m0.092s
$ rvm 1.8.7
$ ruby -v
ruby 1.8.7 (2010年08月16日 patchlevel 302) [i686-linux]
$ time ruby ProtoBufBench
testing ruby-protobuff against ruby-protocol-buffer
The deviation in the deltas was 0.009414
The mean delta was -2.205984
max = -2.18715483485056 :: min = -2.22481263341116
There's no statistical difference
real3m8.131s
user3m7.996s
sys0m0.056s

I didn't try compiling the c extension for ruby-protocol-buffers, and I haven't tried any more involved .proto files yet. I'll work on those in the next couple of days and post results as I see them.
Posted by gnupate

7 comments:

Clayton O'Neill said...

I'd definitely recommend using the java protobuf stuff from JRuby. It works really well and the performance is going to be dramatically better. We've been doing a lot of this lately and we're really happy with it.

3/24/11, 6:08 PM
gnupate said...

@Clayton, thanks for the recommendation. I'll have to give that a try.

3/24/11, 6:27 PM
jarib said...

Would be interesting to compare with beefcake as well.

3/26/11, 2:42 PM
gnupate said...

@jarib, thanks for the pointer to beefcake. I'll be checking it out.

3/26/11, 2:46 PM
Nitin Singh said...

Have you try compiling the c extension for ruby-protocol-buffers?

12/23/14, 8:38 AM
gnupate said...

I haven't tried the c-extension. Have you? What was your experience?

12/23/14, 8:59 AM
Anonymous said...

No I have not. I m trying to do somethin like this in ruby
node::Buffer::Data(val) node::Buffer::Length(val); node::Buffer::HasInstance(value)

Above code is in node.js for c extension. I am looking for any buffer class that I can use to do similar.

12/23/14, 9:19 AM

Post a Comment

Subscribe to: Post Comments (Atom)
 

AltStyle によって変換されたページ (->オリジナル) /