On Sun, 14 Aug 2005, Joe Van Dyk wrote:

>> On Sun, 14 Aug 2005, Joe Van Dyk wrote:
<snip>
> Thanks!  I shall study this code (there's a few new idioms that I
> haven't used before) and report back early next week on the
> performance improvements.

try this one - it's another order of magnitude faster:


     harp:~ > ruby a.rb
     #<PlayerData:0xb75cc0b4 @to_s=nil, @data=[400, 1.0, 2.0, 3.0, 42], @to_bin=nil>
     400
     1.0
     42
     pid : 400, x_position : 1.0, y_position : 2.0, z_position : 3.0, foobar : 42
     creations per second : 114797


     harp:~ > cat a.rb
     class PlayerData
       class << self
         def create(*a)
           new(a.pack(FORMAT))
         end
       end

       SPEC = [
         %w( pid        i ),
         %w( x_position f ),
         %w( y_position f ),
         %w( z_position f ),
         %w( foobar     i ),
       ]

       ATTRIBUTES = SPEC.map{|s| s.first}

       FORMAT = SPEC.map{|s| s.last}.join

       SPEC.each_with_index do |spec, ix|
         at, format = spec
         eval <<-src
           def #{ at }
             @#{ at } ||= @data[#{ ix }]
           end
           def #{ at }= value
             raise TypeError unless self.#{ at }.class == value.class
             uncache
             @#{ at } = @data[#{ ix }] = value
           end
         src
       end

       def update buffer
         uncache
         @data = buffer.unpack FORMAT
       end
       alias initialize update
       def uncache
         @to_s = @to_bin = nil
       end
       def to_s
         @to_s ||= ATTRIBUTES.inject(''){|s,a| s << "#{ a } : #{ send a }, " }.chop.chop
       end
       def to_bin
         @to_bin ||= @data.pack(FORMAT)
       end
     end

     id, x_position, y_position, z_position, foobar =
       400, 1.0, 2.0, 3.0, 0b101010

     pd = PlayerData::create id, x_position, y_position, z_position, foobar

     p pd
     p pd.pid
     p pd.x_position
     p pd.foobar
     puts pd

     begin
       require 'timeout'
       n = 0
       sec = 10
       Timeout::timeout(sec) do
         loop do
           PlayerData::create id, x_position, y_position, z_position, foobar
           n += 1
         end
       end
     rescue Timeout::Error
       puts "creations per second : #{ n / sec }"
     end


basically it just unpacks everything and then uses lazy evaluation to get the
values when asked.  it's hard to imagine getting faster than this, but someone
will surely prove me wrong ;-)

hth.

-a
-- 
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze.  --Nagarjuna
===============================================================================