Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # bad use of metaprogramming
- module MetaTimeDSL
- {:second => 1,
- :minute => 60,
- :hour => 3600,
- :day => [24,:hours],
- :week => [7,:days],
- :month => [30,:days],
- :year => [364.25, :days]}.each do |meth, amount|
- define_method "m_#{meth}" do
- amount = amount.is_a?(Array) ? amount[0].send(amount[1]) : amount
- self * amount
- end
- alias_method "m_#{meth}s".intern, "m_#{meth}"
- end
- end
- Numeric.send :include, MetaTimeDSL
- # Rewrite
- module TimeDSL
- def second
- self * 1
- end
- alias_method :seconds, :second
- def minute
- self * 60
- end
- alias_method :minutes, :minute
- def hour
- self * 3600
- end
- alias_method :hours, :hour
- def day
- self * 86400
- end
- alias_method :days, :day
- def week
- self * 604800
- end
- alias_method :weeks, :week
- def month
- self * 18144000
- end
- alias_method :months, :month
- def year
- self * 31471200
- end
- alias_method :years, :year
- end
- Numeric.send :include, TimeDSL
- module RefaMetaTimeDSL
- {:second => 1,
- :minute => 60,
- :hour => 3600,
- :day => [24,:hours],
- :week => [7,:days],
- :month => [30,:days],
- :year => [364.25, :days]}.each do |meth, amount|
- self.class_eval <<-RUBY
- def r_#{meth}
- #{amount.is_a?(Array) ? "#{amount[0]}.#{amount[1]}" : "#{amount}"}
- end
- alias_method :r_#{meth}s, :r_#{meth}
- RUBY
- end
- end
- Numeric.send :include, RefaMetaTimeDSL
- module EvalMetaTimeDSL
- def self.included(base)
- base.class_eval do
- [ [:e_second, 1],
- [:e_minute, 60],
- [:e_hour, 3600],
- [:e_day, [24,:e_hours]],
- [:e_week, [7,:e_days]],
- [:e_month, [30,:e_days]],
- [:e_year, [365.25, :e_days]]].each do |meth, amount|
- amount = amount.is_a?(Array) ? amount[0].send(amount[1]) : amount
- eval "def #{meth}; self*#{amount}; end"
- alias_method "#{meth}s", meth
- end
- end
- end
- end
- Numeric.send :include, EvalMetaTimeDSL
- module GoodMetaTimeDSL
- SECOND = 1
- MINUTE = SECOND * 60
- HOUR = MINUTE * 60
- DAY = HOUR * 24
- WEEK = DAY * 7
- MONTH = DAY * 30
- YEAR = DAY * 364.25
- %w[SECOND MINUTE HOUR DAY WEEK MONTH YEAR].each do |const_name|
- meth = const_name.downcase
- class_eval <<-RUBY
- def g_#{meth}
- self * #{const_name}
- end
- alias g_#{meth}s g_#{meth}
- RUBY
- end
- end
- Numeric.send :include, GoodMetaTimeDSL
- ###############################
- #
- #
- # Benchmarks
- require "rubygems"
- require "rbench"
- TIMES = 100_000
- RBench.run(TIMES) do
- format :width => 65
- column :times
- column :bad_meta, :title => "Bad Neta"
- column :no_meta, :title => "No Meta"
- column :refa, :title => "Refactored"
- column :eval_meta, :title => 'Refactor 2'
- column :good_meta, :title => "Better Meta"
- group("MetaTimeDSL") do
- report "with 360.seconds" do
- bad_meta { 360.m_seconds }
- no_meta { 360.seconds }
- refa { 360.r_seconds }
- eval_meta { 360.e_seconds}
- good_meta { 360.g_seconds }
- end
- report "with 360.minutes" do
- bad_meta { 360.m_minutes }
- no_meta { 360.minutes }
- refa { 360.r_minutes }
- eval_meta { 360.e_minutes }
- good_meta { 360.g_minutes }
- end
- report "with 360.hours" do
- bad_meta { 360.m_hours }
- no_meta { 360.hours }
- refa { 360.r_hours }
- eval_meta { 360.e_hours }
- good_meta { 360.g_hours }
- end
- report "with 360.days" do
- bad_meta { 360.m_days }
- no_meta { 360.days }
- refa { 360.r_days }
- eval_meta { 360.e_days }
- good_meta { 360.g_days }
- end
- report "with 360.weeks" do
- bad_meta { 360.m_weeks }
- no_meta { 360.weeks }
- refa { 360.r_weeks }
- eval_meta { 360.e_weeks }
- good_meta { 360.g_weeks }
- end
- report "with 18.months" do
- bad_meta { 18.m_months }
- no_meta { 18.months }
- refa { 18.r_months }
- eval_meta { 18.e_months }
- good_meta { 18.g_months }
- end
- report "with 7.years" do
- bad_meta { 7.m_years }
- no_meta { 7.years }
- refa { 7.r_years }
- eval_meta { 7.e_years }
- good_meta { 7.g_years }
- end
- end
- end
- #####
- #
- # | Bad Neta | No Meta | Refactored | Refactor 2 | Better Meta |
- # --MetaTimeDSL----------------------------------------------------------------------------------
- # with 360.seconds x100000 | 0.143 | 0.046 | 0.033 | 0.047 | 0.048 |
- # with 360.minutes x100000 | 0.152 | 0.045 | 0.033 | 0.046 | 0.046 |
- # with 360.hours x100000 | 0.127 | 0.044 | 0.032 | 0.045 | 0.048 |
- # with 360.days x100000 | 0.144 | 0.047 | 0.070 | 0.045 | 0.048 |
- # with 360.weeks x100000 | 0.129 | 0.044 | 0.070 | 0.046 | 0.047 |
- # with 18.months x100000 | 0.143 | 0.045 | 0.071 | 0.045 | 0.048 |
- # with 7.years x100000 | 0.143 | 0.046 | 0.089 | 0.054 | 0.050 |
- #
- ####
Add Comment
Please, Sign In to add comment