Project

General

Profile

Actions

Backport #3359

closed

Date::Format::Bag performance improvement

Added by kstephens (Kurt Stephens) almost 14 years ago. Updated almost 5 years ago.

Status:
Closed
Assignee:
-
[ruby-core:30476]

Description

=begin
Date::Format::Bag spends a lot of time in method_missing for a limited number of method selectors.

The hack below removed ~ 3% of time from a ActiveRecord/Rails app that parses and formats many Date objects.

 class Date::Format::Bag
     def method_missing(sel, *args) # , &block)
       sel = sel.to_s
       t = sel.dup
       set = t.chomp!('=')
       t = t.intern
       if set
         value = @elem[t] = args[0]
         expr = "def #{sel}(arg); @elem[#{t.inspect}] = arg; end"
       else
         value = @elem[t]
         #
         # There appear to be no callers like:
         #
         #   e.foo(something)
         #
         # Thus do not interpret any arguments as
         # the *rest parameter creates Arrays that are
         # never referenced.
         #
         # expr = "def #{sel}(*rest); @elem[#{t.inspect}]; end"
         expr = "def #{sel}(); @elem[#{t.inspect}]; end"
       end
       expr = "class #{self.class}; #{expr}; end;"
       # $stderr.puts "  **** #{self.class}\##{sel} => #{expr}"
       eval(expr)
       value
     end
   end
 

Might be better to just enumerate all the possible Hash slot getter/setters using a simple class macro,
since Date::Format::Bag is not used by anything outside of Date.
=end

Actions #1

Updated by kstephens (Kurt Stephens) almost 14 years ago

=begin
This version is a bit more succinct:

  class Date::Format::Bag
     def method_missing(sel, *args) # , &block)
       sel = sel.to_s
       t = sel.dup
       set = t.chomp!('=')
       t = t.intern
 
       #
       # There appear to be no callers like:
       #
       #   e.foo(something)
       #
       # Thus do not interpret any arguments as
       # the *rest parameter since it creates Arrays 
       # that are never referenced in:
       # 
       #   def foo(*rest); @elem[:foo]; end
       #
       expr = \n#{expr}"
       eval(expr)
 
       if set
         @elem[t] = args[0]
       else
         @elem[t]
       end
     end
   end
 

=end

Actions #2

Updated by jeremyevans0 (Jeremy Evans) almost 5 years ago

  • Tracker changed from Bug to Backport
  • Project changed from Ruby 1.8 to Backport187
  • Description updated (diff)
  • Status changed from Open to Closed
  • ruby -v deleted (ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux])
Actions

Also available in: Atom PDF

Like0
Like0Like0