logging - Ruby: Proxy pattern, reducing method calls -


how proxy ruby logger , keep performance?

so, have requirement @ work, quite reasonable. when program sent signal hup log flushed , restarted.

class localobject    attr_accessor :logger    def initialize context     # 1 less method call! yea! performance++     @logger = context.logger   end    def     @logger.info "hello world"   end  end 

the problem, if context.logger reset, @logger still points old one.

so, thought proxy logger:

class loggerproxy   attr_accessor :logger    def debug *args     @logger.send :debug, args   end    def info *args     @logger.send :info, args   end end  context.logger = loggerproxy.new context.logger.logger = logger.new 'my_file.log'  signal.trap('hup') {    context.logger.logger = logger.new 'my_file.log' } ... @logger = context.logger @logger.info "hello world" 

this works fine, except i've traded 1 method call 2 method calls (1 accessor; returns logger). still have call loggerproxy.:debug, :info, ..., in turn calls original logger! ergo, 2 methods calls, there one.

i don't want monkey logger class, or overload it, because want use other loggers in future, syslog, roll own, or such.

is there way reduce number of method calls performance?

-daniel

update: in response question performance, here sample test.

require 'logger' require 'benchmark';  class mylogger    attr_accessor :logger    def info msg     @logger.info msg   end  end  mylogger = logger.new '/dev/null' # dev null avoid io issues myloggerproxy = mylogger.new myloggerproxy.logger = mylogger  n = 100000 benchmark.bm | benchmarker |   # plain logger   benchmarker.report { n.times { mylogger.info 'opps' } }    # via accessor   benchmarker.report { n.times { myloggerproxy.logger.info 'opps' } }    # via proxy   benchmarker.report { n.times { myloggerproxy.info 'opps' } } end         user     system      total        real   1.580000   0.150000   1.730000 (  1.734956)   1.600000   0.150000   1.750000 (  1.747969)   1.610000   0.160000   1.770000 (  1.767886) 

first: question smells you're optimizing prematurely. should optimize if know code slow. (and benchmark show tiny difference)

that said, make context notify every proxy if logger ever updated:

class proxylogger   attr_accessor :logger    def initialize(context)     context.register(self)   end end  class context   attr_accessor :logger    def initialize     @proxies = []   end    def logger=(val)     @logger = val     @proxies.each { |p| p.logger = val }   end    def register(proxy)     @proxies << proxy   end end 

but again, not seem worth additional complexity.

(related: this nice presentation showing @tenderlove optimizing arel gem)


Comments

Popular posts from this blog

asp.net - repeatedly call AddImageUrl(url) to assemble pdf document -

java - Android recognize cell phone with keyboard or not? -

iphone - How would you achieve a LED Scrolling effect? -