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