On 8/13/05, Ara.T.Howard <Ara.T.Howard / noaa.gov> wrote:
> On Sun, 14 Aug 2005, Joe Van Dyk wrote:
> 
> > Ah, ok.  In my application, there's a bunch more than 3 possible keys and
> > they are of differing length.  I am in control of the format of the incoming
> > strings though, and so could modify their format to make them easier/faster
> > to parse.  Any ideas on what would be a more efficient format for
> > transporting the data?
> 
> binary.
> 
> > (for reference, the original string format was "id: 3, x_position: 39,
> > y_position: 209, z_position: 39" and in my real application, there's about
> > twenty different attributes that are in the string.)
> >
> > Perhaps it would be more efficient to not convert the string into a hash?
> >
> > All I really need to be able to do is access/display a player's data via
> > some mechanism, and a player's data should be updated once a second, and
> > there's up to 400 players.  The above was the best way I could come up with
> > transporting and accessing the data, but perhaps there's a better way of
> > doing it.
> 
> something similar in spirit to this would support many players:
> 
>      harp:~ > cat a.rb
>      class PlayerData
>        ATTRIBUTES = %w(
>          id
>          x_position
>          y_position
>          z_position
>          foobar
>        ).each{|a| attr a}
> 
>        FORMAT = 'ifffi'
> 
>        class << self
>          def create(*a); new(a.flatten.pack(FORMAT)); end
>        end
> 
>        attr :buffer
>        attr :to_s
> 
>        def update buffer
>          ATTRIBUTES.zip((@buffer = buffer).unpack(FORMAT)) do |a,v|
>            instance_variable_set "@#{ a }", v
>          end
>          @to_s = ATTRIBUTES.inject(''){|s,a| s << "#{ a } : #{ send a }, " }.chop.chop
>        end
>        alias initialize update
>      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.id
>      p pd.x_position
>      p pd.foobar
>      puts pd
> 
> 
>      begin
>        require 'timeout'
>        n = 0
>        Timeout::timeout(10) 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 / 10 }"
>      end
> 
> 
>      harp:~ > ruby a.rb
>      #<PlayerData:0xb75cdf04 @x_position=1.0, @foobar=42, @id=400, @buffer="\220\001\000\000\000\000\200?\000\000\000@\000\000@@*\000\000\000", @z_position=3.0, @to_s="id : 400, x_position : 1.0, y_position : 2.0, z_position : 3.0, foobar : 42", @y_position=2.0>
>      400
>      1.0
>      42
>      id : 400, x_position : 1.0, y_position : 2.0, z_position : 3.0, foobar : 42
>      creations per second : 14045
> 
> not to mention the message (player data strings) will be an order of
> magintitude smaller to pass around - like over a network.

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.