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:
I compiled this with
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:
for ruby-protocol-buffer:
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.
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.
Labels:
benchmarking,
protocol buffer
Subscribe to:
Post Comments (Atom)
7 comments:
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.
@Clayton, thanks for the recommendation. I'll have to give that a try.
Would be interesting to compare with beefcake as well.
@jarib, thanks for the pointer to beefcake. I'll be checking it out.
Have you try compiling the c extension for ruby-protocol-buffers?
I haven't tried the c-extension. Have you? What was your experience?
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.
Post a Comment