On Thu, Dec 29, 2005 at 06:51:29AM +0900, ara.t.howard / noaa.gov wrote:
> On Thu, 29 Dec 2005, Johannes Friestad wrote:
> >That's where the 'can be' part comes in :)
> >The point is that symbols support quicker lookup by their nature.
> >Whether they are quicker in practice will depend on the
> >implementation. From the timings you give, it looks like symbol lookup
> >is implemented by converting the symbol to a string and doing string
> >lookup. Which is obviously not quicker :)
> 
> i never consider that as an impl - i bet your right though... time for me to
> read the source.

I think :sym.hash uses the method definition from Kernel (inherited through
Object) and :sym.eql?(:foo) would also reuse the existing definition.

[see C code at the bottom]

So there's seemingly no reason for symbol hashing/comparison not to be
faster than for strings. The benchmarks you linked to, as well as Jim's,
use relatively short strings, but one can exaggerate the effect:


# >> Strings Filling
# >>   5.800000   0.000000   5.800000 (  6.302649)
# >> Strings Fetching
# >>   3.120000   0.010000   3.130000 (  3.404679)
# >> 
# >> Symbols Filling
# >>   2.120000   0.000000   2.120000 (  2.326393)
# >> Symbols Fetching
# >>   0.640000   0.000000   0.640000 (  0.700178)


#!/usr/bin/env ruby require 'benchmark' SIZE = 100 N = 10000 RUBY_VERSION # => "1.8.4" def make_str_keys (1..SIZE).collect { |i| "long key" * i} end def make_sym_keys(strs) strs.collect { |s| s.intern } end def populate(keys) result = {} keys.each_with_index do |k, i| result[k] = i end result end def fetch(keys, hash) keys.each do |key| hash[key] end end strs = make_str_keys syms = make_sym_keys(strs) str_hash = populate(strs) sym_hash = populate(syms) puts "Strings Filling" puts Benchmark.measure { N.times do populate(strs) end } puts "Strings Fetching" puts Benchmark.measure { N.times do fetch(strs, str_hash) end } puts puts "Symbols Filling" puts Benchmark.measure { N.times do populate(syms) end } puts "Symbols Fetching" puts Benchmark.measure { N.times do fetch(syms, sym_hash) end }
rb_define_method(rb_mKernel, "hash", rb_obj_id, 0); ... VALUE rb_obj_id(VALUE obj) { if (SPECIAL_CONST_P(obj)) { return LONG2NUM((long)obj); } return (VALUE)((long)obj|FIXNUM_FLAG); } rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1); ... static VALUE rb_obj_equal(VALUE obj1, VALUE obj2) { if (obj1 == obj2) return Qtrue; return Qfalse; } -- Mauricio Fernandez