From 6c70c02c83b3a03c88df4286130be8882f6d201c Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 7 Aug 2008 23:31:43 -0700 Subject: Freeze memoized results when instance is frozen instead of immediately so you can memoize mutable objects --- activesupport/lib/active_support/memoizable.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index e6049d9496..b5adc2330c 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -14,7 +14,7 @@ module ActiveSupport methods.each do |method| if method.to_s =~ /^_unmemoized_(.*)/ begin - __send__($1) + __send__($1).freeze rescue ArgumentError end end @@ -41,7 +41,7 @@ module ActiveSupport if !reload && defined? #{memoized_ivar} #{memoized_ivar} else - #{memoized_ivar} = #{original_method}.freeze + #{memoized_ivar} = #{original_method} end end else @@ -52,7 +52,7 @@ module ActiveSupport if !reload && #{memoized_ivar} && #{memoized_ivar}.has_key?(args) #{memoized_ivar}[args] else - #{memoized_ivar}[args] = #{original_method}(*args).freeze + #{memoized_ivar}[args] = #{original_method}(*args) end end end -- cgit v1.2.3 From 282b42021306f73d4cc8f8a06713da9a55ed044b Mon Sep 17 00:00:00 2001 From: Jeffrey Hardy Date: Wed, 13 Aug 2008 00:51:47 -0400 Subject: Account for the possibility of a nil options argument to CompressedMemCacheStore#read/#write --- .../lib/active_support/cache/compressed_mem_cache_store.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/cache/compressed_mem_cache_store.rb b/activesupport/lib/active_support/cache/compressed_mem_cache_store.rb index 9470ac9f66..0bff6cf9ad 100644 --- a/activesupport/lib/active_support/cache/compressed_mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/compressed_mem_cache_store.rb @@ -1,14 +1,14 @@ module ActiveSupport module Cache class CompressedMemCacheStore < MemCacheStore - def read(name, options = {}) - if value = super(name, options.merge(:raw => true)) + def read(name, options = nil) + if value = super(name, (options || {}).merge(:raw => true)) Marshal.load(ActiveSupport::Gzip.decompress(value)) end end - def write(name, value, options = {}) - super(name, ActiveSupport::Gzip.compress(Marshal.dump(value)), options.merge(:raw => true)) + def write(name, value, options = nil) + super(name, ActiveSupport::Gzip.compress(Marshal.dump(value)), (options || {}).merge(:raw => true)) end end end -- cgit v1.2.3 From 3fc9a67c04bade858e7ac7eb8cd94eec6a63ec27 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 13 Aug 2008 17:22:38 -0700 Subject: memoize_ and unmemoize_all --- activesupport/lib/active_support/memoizable.rb | 51 +++++++++++++++++--------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index b5adc2330c..5aa73bce52 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -10,25 +10,37 @@ module ActiveSupport end def freeze_with_memoizable - unless frozen? - methods.each do |method| - if method.to_s =~ /^_unmemoized_(.*)/ - begin - __send__($1).freeze - rescue ArgumentError - end + memoize_all unless frozen? + freeze_without_memoizable + end + + def memoize_all + methods.each do |m| + if m.to_s =~ /^_unmemoized_(.*)/ + if method(m).arity == 0 + __send__($1) + else + ivar = :"@_memoized_#{$1}" + instance_variable_set(ivar, {}) end end end + end - freeze_without_memoizable + def unmemoize_all + methods.each do |m| + if m.to_s =~ /^_unmemoized_(.*)/ + ivar = :"@_memoized_#{$1}" + instance_variable_get(ivar).clear if instance_variable_defined?(ivar) + end + end end end def memoize(*symbols) symbols.each do |symbol| - original_method = "_unmemoized_#{symbol}" - memoized_ivar = "@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}" + original_method = :"_unmemoized_#{symbol}" + memoized_ivar = :"@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}" class_eval <<-EOS, __FILE__, __LINE__ include Freezable @@ -38,21 +50,24 @@ module ActiveSupport if instance_method(:#{symbol}).arity == 0 def #{symbol}(reload = false) - if !reload && defined? #{memoized_ivar} - #{memoized_ivar} - else - #{memoized_ivar} = #{original_method} + if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? + #{memoized_ivar} = [#{original_method}] end + #{memoized_ivar}[0] end else def #{symbol}(*args) - #{memoized_ivar} ||= {} + #{memoized_ivar} ||= {} unless frozen? reload = args.pop if args.last == true || args.last == :reload - if !reload && #{memoized_ivar} && #{memoized_ivar}.has_key?(args) - #{memoized_ivar}[args] + if #{memoized_ivar} + if !reload && #{memoized_ivar}.has_key?(args) + #{memoized_ivar}[args] + elsif #{memoized_ivar} + #{memoized_ivar}[args] = #{original_method}(*args) + end else - #{memoized_ivar}[args] = #{original_method}(*args) + #{original_method}(*args) end end end -- cgit v1.2.3 From b8b30985d525fd15b6c16d29fc115e83e3ee5037 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 13 Aug 2008 20:57:26 -0500 Subject: Marshal FileStore values --- activesupport/lib/active_support/cache/file_store.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index 7b6ca39091..437679cc05 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -9,13 +9,13 @@ module ActiveSupport def read(name, options = nil) super - File.open(real_file_path(name), 'rb') { |f| f.read } rescue nil + File.open(real_file_path(name), 'rb') { |f| Marshal.load(f) } rescue nil end def write(name, value, options = nil) super ensure_cache_path(File.dirname(real_file_path(name))) - File.atomic_write(real_file_path(name), cache_path) { |f| f.write(value) } + File.atomic_write(real_file_path(name), cache_path) { |f| Marshal.dump(value, f) } rescue => e RAILS_DEFAULT_LOGGER.error "Couldn't create cache directory: #{name} (#{e.message})" if RAILS_DEFAULT_LOGGER end -- cgit v1.2.3 From 8cb14ee1203c9ed380c4b192e8730757a52d43cb Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 13 Aug 2008 21:30:46 -0500 Subject: Ensure results returned by a memoized method are immutable --- activesupport/lib/active_support/memoizable.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 5aa73bce52..6506238ac0 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -51,7 +51,7 @@ module ActiveSupport if instance_method(:#{symbol}).arity == 0 def #{symbol}(reload = false) if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? - #{memoized_ivar} = [#{original_method}] + #{memoized_ivar} = [#{original_method}.freeze] end #{memoized_ivar}[0] end @@ -64,7 +64,7 @@ module ActiveSupport if !reload && #{memoized_ivar}.has_key?(args) #{memoized_ivar}[args] elsif #{memoized_ivar} - #{memoized_ivar}[args] = #{original_method}(*args) + #{memoized_ivar}[args] = #{original_method}(*args).freeze end else #{original_method}(*args) -- cgit v1.2.3 From 7fbe226de5c63565fcca67d01687d83009ab9886 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 7 Aug 2008 01:22:03 -0700 Subject: Ruby 1.9 and GC::Profiler updates --- .../lib/active_support/testing/performance.rb | 66 ++++++++++++++++++++-- 1 file changed, 60 insertions(+), 6 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 70a7f84023..3ad7289571 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -25,7 +25,7 @@ module ActiveSupport def self.included(base) base.class_inheritable_hash :profile_options - base.profile_options = DEFAULTS.dup + base.profile_options = DEFAULTS end def full_test_name @@ -34,6 +34,7 @@ module ActiveSupport def run(result) return if method_name =~ /^default_test$/ + self.profile_options ||= DEFAULTS yield(self.class::STARTED, name) @_result = result @@ -43,8 +44,6 @@ module ActiveSupport if klass = Metrics[metric_name.to_sym] run_profile(klass.new) result.add_run - else - $stderr.puts '%20s: unsupported' % metric_name.to_s end end @@ -164,7 +163,14 @@ module ActiveSupport end class Profiler < Performer + def initialize(*args) + super + @supported = @metric.measure_mode rescue false + end + def run + return unless @supported + RubyProf.measure_mode = @metric.measure_mode RubyProf.start RubyProf.pause @@ -173,7 +179,17 @@ module ActiveSupport @total = @data.threads.values.sum(0) { |method_infos| method_infos.sort.last.total_time } end + def report + if @supported + super + else + '%20s: unsupported' % @metric.name + end + end + def record + return unless @supported + klasses = profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact klasses.each do |klass| @@ -202,8 +218,7 @@ module ActiveSupport module Metrics def self.[](name) - klass = const_get(name.to_s.camelize) - klass if klass::Mode + const_get(name.to_s.camelize) rescue NameError nil end @@ -250,6 +265,16 @@ module ActiveSupport ensure GC.disable_stats end + elsif defined?(GC::Profiler) + def with_gc_stats + GC.start + GC.disable + GC::Profiler.enable + yield + ensure + GC::Profiler.disable + GC.enable + end else def with_gc_stats yield @@ -310,7 +335,7 @@ module ActiveSupport RubyProf.measure_memory / 1024.0 end - # Ruby 1.8 + adymo patch + # Ruby 1.8 + railsbench patch elsif GC.respond_to?(:allocated_size) def measure GC.allocated_size / 1024.0 @@ -322,11 +347,27 @@ module ActiveSupport GC.heap_info['heap_current_memory'] / 1024.0 end + # Ruby 1.9 with total_malloc_allocated_size patch + elsif GC.respond_to?(:malloc_total_allocated_size) + def measure + GC.total_malloc_allocated_size / 1024.0 + end + # Ruby 1.9 unpatched elsif GC.respond_to?(:malloc_allocated_size) def measure GC.malloc_allocated_size / 1024.0 end + + # Ruby 1.9 + GC profiler patch + elsif defined?(GC::Profiler) + def measure + GC.enable + GC.start + kb = GC::Profiler.data.last[:HEAP_USE_SIZE] / 1024.0 + GC.disable + kb + end end def format(measurement) @@ -341,10 +382,23 @@ module ActiveSupport def measure RubyProf.measure_allocations end + + # Ruby 1.8 + railsbench patch elsif ObjectSpace.respond_to?(:allocated_objects) def measure ObjectSpace.allocated_objects end + + # Ruby 1.9 + GC profiler patch + elsif defined?(GC::Profiler) + def measure + GC.enable + GC.start + last = GC::Profiler.data.last + count = last[:HEAP_LIVE_OBJECTS] + last[:HEAP_FREE_OBJECTS] + GC.disable + count + end end def format(measurement) -- cgit v1.2.3 From a4da8175a2c989104de1a38e43d5ddfb0f89b055 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 18 Aug 2008 20:14:56 -0500 Subject: Replace MemoryStore mutex with a monitor to avoid issues with nested calls --- .../lib/active_support/cache/memory_store.rb | 36 ++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb index a44f877414..7ac6f35357 100644 --- a/activesupport/lib/active_support/cache/memory_store.rb +++ b/activesupport/lib/active_support/cache/memory_store.rb @@ -3,51 +3,63 @@ module ActiveSupport class MemoryStore < Store def initialize @data = {} - @mutex = Mutex.new + @guard = Monitor.new end def fetch(key, options = {}) - @mutex.synchronize do + @guard.synchronize do super end end def read(name, options = nil) - super - @data[name] + @guard.synchronize do + super + @data[name] + end end def write(name, value, options = nil) - super - @data[name] = value + @guard.synchronize do + super + @data[name] = value + end end def delete(name, options = nil) - @data.delete(name) + @guard.synchronize do + @data.delete(name) + end end def delete_matched(matcher, options = nil) - @data.delete_if { |k,v| k =~ matcher } + @guard.synchronize do + @data.delete_if { |k,v| k =~ matcher } + end end def exist?(name,options = nil) - @data.has_key?(name) + @guard.synchronize do + @data.has_key?(name) + end end def increment(key, amount = 1) - @mutex.synchronize do + @guard.synchronize do super end end def decrement(key, amount = 1) - @mutex.synchronize do + @guard.synchronize do super end end def clear - @data.clear + @guard.synchronize do + @data.clear + end end end end -- cgit v1.2.3 From c1a8690d582c08777055caf449c03f85b4c8aa4b Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 18 Aug 2008 22:38:58 -0500 Subject: Consistently use the framework's configured logger and avoid reverting to RAILS_DEFAULT_LOGGER unless necessary. --- activesupport/lib/active_support/cache/file_store.rb | 4 ++-- activesupport/lib/active_support/core_ext/kernel/debugger.rb | 8 ++++---- activesupport/lib/active_support/dependencies.rb | 10 +++++++--- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index 437679cc05..659bde64f0 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -17,7 +17,7 @@ module ActiveSupport ensure_cache_path(File.dirname(real_file_path(name))) File.atomic_write(real_file_path(name), cache_path) { |f| Marshal.dump(value, f) } rescue => e - RAILS_DEFAULT_LOGGER.error "Couldn't create cache directory: #{name} (#{e.message})" if RAILS_DEFAULT_LOGGER + logger.error "Couldn't create cache directory: #{name} (#{e.message})" if logger end def delete(name, options = nil) @@ -67,4 +67,4 @@ module ActiveSupport end end end -end \ No newline at end of file +end diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb index c74d6cf884..4007a647be 100644 --- a/activesupport/lib/active_support/core_ext/kernel/debugger.rb +++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb @@ -2,12 +2,12 @@ module Kernel unless respond_to?(:debugger) # Starts a debugging session if ruby-debug has been loaded (call script/server --debugger to do load it). def debugger - RAILS_DEFAULT_LOGGER.info "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n" + Rails.logger.info "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n" end end - + def breakpoint - RAILS_DEFAULT_LOGGER.info "\n***** The 'breakpoint' command has been renamed 'debugger' -- please change *****\n" + Rails.logger.info "\n***** The 'breakpoint' command has been renamed 'debugger' -- please change *****\n" debugger end -end \ No newline at end of file +end diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index a3f5f799a2..3d871eec11 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -39,6 +39,10 @@ module ActiveSupport #:nodoc: mattr_accessor :explicitly_unloadable_constants self.explicitly_unloadable_constants = [] + # The logger is used for generating information on the action run-time (including benchmarking) if available. + # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. + mattr_accessor :logger + # Set to true to enable logging of const_missing and file loads mattr_accessor :log_activity self.log_activity = false @@ -584,7 +588,7 @@ module ActiveSupport #:nodoc: protected def log_call(*args) - if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER && log_activity + if logger && log_activity arg_str = args.collect { |arg| arg.inspect } * ', ' /in `([a-z_\?\!]+)'/ =~ caller(1).first selector = $1 || '' @@ -593,8 +597,8 @@ module ActiveSupport #:nodoc: end def log(msg) - if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER && log_activity - RAILS_DEFAULT_LOGGER.debug "Dependencies: #{msg}" + if logger && log_activity + logger.debug "Dependencies: #{msg}" end end end -- cgit v1.2.3 From 96ab01e8f2b5a4475453acf60f9cf9bd8cd98483 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 18 Aug 2008 23:33:46 -0500 Subject: Maintain a seperate buffer for each thread --- activesupport/lib/active_support/buffered_logger.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index cedc1afe7f..6553d72b4f 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -33,11 +33,10 @@ module ActiveSupport attr_accessor :level attr_reader :auto_flushing - attr_reader :buffer def initialize(log, level = DEBUG) @level = level - @buffer = [] + @buffer = {} @auto_flushing = 1 @guard = Mutex.new @@ -60,9 +59,7 @@ module ActiveSupport # If a newline is necessary then create a new message ending with a newline. # Ensures that the original message is not mutated. message = "#{message}\n" unless message[-1] == ?\n - @guard.synchronize do - buffer << message - end + buffer << message auto_flush message end @@ -96,8 +93,8 @@ module ActiveSupport def flush @guard.synchronize do unless buffer.empty? - old_buffer = @buffer - @buffer = [] + old_buffer = buffer + clear_buffer @log.write(old_buffer.join) end end @@ -113,5 +110,13 @@ module ActiveSupport def auto_flush flush if buffer.size >= @auto_flushing end + + def buffer + @buffer[Thread.current] ||= [] + end + + def clear_buffer + @buffer[Thread.current] = [] + end end end -- cgit v1.2.3 From 5de340e79f1d11973b7c7bbec82f320fc92b9c99 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 19 Aug 2008 19:20:10 -0500 Subject: Ensure objects cached with MemoryStore are immutable --- activesupport/lib/active_support/cache/memory_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb index 7ac6f35357..f3e4b8c13b 100644 --- a/activesupport/lib/active_support/cache/memory_store.rb +++ b/activesupport/lib/active_support/cache/memory_store.rb @@ -22,7 +22,7 @@ module ActiveSupport def write(name, value, options = nil) @guard.synchronize do super - @data[name] = value + @data[name] = value.freeze end end -- cgit v1.2.3 From f388725bd61d8ae246c0c8e42eaec1a2be4620ac Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 21 Aug 2008 00:28:25 -0500 Subject: Partial revert of 2681685 premature TypeArray abstraction --- activesupport/lib/active_support/typed_array.rb | 31 ------------------------- 1 file changed, 31 deletions(-) delete mode 100644 activesupport/lib/active_support/typed_array.rb (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/typed_array.rb b/activesupport/lib/active_support/typed_array.rb deleted file mode 100644 index 1a4d8a8faf..0000000000 --- a/activesupport/lib/active_support/typed_array.rb +++ /dev/null @@ -1,31 +0,0 @@ -module ActiveSupport - class TypedArray < Array - def self.type_cast(obj) - obj - end - - def initialize(*args) - super(*args).map! { |obj| self.class.type_cast(obj) } - end - - def <<(obj) - super(self.class.type_cast(obj)) - end - - def concat(array) - super(array.map! { |obj| self.class.type_cast(obj) }) - end - - def insert(index, obj) - super(index, self.class.type_cast(obj)) - end - - def push(*objs) - super(*objs.map { |obj| self.class.type_cast(obj) }) - end - - def unshift(*objs) - super(*objs.map { |obj| self.class.type_cast(obj) }) - end - end -end -- cgit v1.2.3 From 6be8251ec86b74b92e7bd922fafe9224281d2d26 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 21 Aug 2008 00:51:06 -0500 Subject: Simplified and renamed CallbackChain union method to replace_or_append! --- activesupport/lib/active_support/callbacks.rb | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 9c59b7ac76..7b905930bb 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -96,15 +96,12 @@ module ActiveSupport end end - def |(chain) - if chain.is_a?(CallbackChain) - chain.each { |callback| self | callback } + # TODO: Decompose into more Array like behavior + def replace_or_append!(chain) + if index = index(chain) + self[index] = chain else - if (found_callback = find(chain)) && (index = index(chain)) - self[index] = chain - else - self << chain - end + self << chain end self end @@ -157,6 +154,14 @@ module ActiveSupport self.class.new(@kind, @method, @options.dup) end + def hash + if @identifier + @identifier.hash + else + @method.hash + end + end + def call(*args, &block) evaluate_method(method, *args, &block) if should_run_callback?(*args) rescue LocalJumpError -- cgit v1.2.3