* Lyle Johnson <lyle / users.sourceforge.net>:

> If nothing else, it may help to reduce the amount of string allocation,
> deallocation, etc. in your programs. For example, if I wrote the following
> snippet in Ruby:
> 
>      allUsers.each do |userName|
>        if userName == "Christopher"
>          # found a match
>        end
>      end
> 
> Ruby would (presumably) allocate a new (temporary) string object, with the
> contents "Christopher", for each pass through the loop. It would also
> perform that many character-by-character string comparisons. For a lot of
> user names, that's going to be slow. In contrast, this bit of code:
> 
>      allUsers.each do |userName|
>        if userName.intern == :Christopher
>          # found a match
>        end
>      end
> 
> would run significantly faster since the "Christopher" symbol gets added
> to the symbol table once and subsequent references just point to that
> entry. 

But wouldn't doing that intern each time in the loop hurt you more? I tested
the above idea with this code:

-- cut here ----------------------------------------------------------------
require "profile"

def string_test( a )
  a.each do |s|
    if s == "MMM"
      # Do nothing
    end
  end
end

def symbol_test( a )
  a.each do |s|
    if s.intern == :MMM
      # Do nothing
    end
  end
end

a = ( "AAA" .. "ZZZ" ).collect

string_test( a )
symbol_test( a )
-- cut here ----------------------------------------------------------------

and found that the symbol comparison test was slower:

,----
|   0.00    26.11      0.00        1     0.00 13620.00  Object#symbol_test
|   0.00    26.11      0.00        1     0.00  7460.00  Object#string_test
`----

>        Also, since Symbol objects mainly consist of an index into the
> symbol table, comparing symbols is very fast -- as fast as comparing two
> integer values to each other. This code could be made even faster if the
> "allUsers" array stored symbols directly instead of storing strings, but
> you get the idea.

That does make a difference but it doesn't seem to be a very significant
gain, not as significant as the above paragraph might suggest:

-- cut here ----------------------------------------------------------------
require "profile"

def string_test( a )
  a.each do |s|
    if s == "MMM"
      # Do nothing
    end
  end
end

def symbol_test( a )
  a.each do |s|
    if s == :MMM
      # Do nothing
    end
  end
end

a = ( "AAA" .. "ZZZ" ).collect
s = a.collect {|s| s.intern }

string_test( a )
symbol_test( s )
-- cut here ----------------------------------------------------------------

Giving:

,----
|   0.00    29.43      0.00        1     0.00  7860.00  Object#symbol_test
|   0.00    29.43      0.00        1     0.00  8080.00  Object#string_test
`----

Am I missing something here?

-- 
Dave Pearson
http://www.davep.org/