如何代理ruby記錄器並保持性能?Ruby:代理模式,減少方法調用
所以,我們有一個工作要求,很合理。當程序發送信號HUP 時,日誌將被刷新並重新啓動。
class LocalObject
attr_accessor :logger
def initialize context
# one less method call! Yea! performance++
@logger = context.logger
end
def something
@logger.info "Hello world"
end
end
問題是,如果context.logger被重置,那麼@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"
這工作得很好,但我換一個方法調用2次方法調用(1次訪問;它返回的記錄器)。我仍然需要調用LoggerProxy.:debug,:info,...,然後調用原始記錄器! Ergo,2個方法調用,其中有一個。
我不想用Logger類來猴子,或者重載它,因爲我想在將來使用其他記錄器,syslog,滾動我自己的,或者其他的。
有沒有辦法減少性能方法調用的次數?
-daniel
更新:在回答關於性能的問題,這裏是樣本測試。
require 'logger'
require 'benchmark';
class MyLogger
attr_accessor :logger
def info msg
@logger.info msg
end
end
myLogger = Logger.new '/dev/null' # dev null to avoid IO issues
myLoggerProxy = MyLogger.new
myLoggerProxy.logger = myLogger
n = 100000
Benchmark.bm do | 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)
Ohmygoodness。除非我錯誤得多,否則這與博客無關,所以我刪除了「博客」標籤。 – 2010-12-01 00:13:17
@Jonathan:如果你在標籤列表中輸入「logger」,然後按tab,你會得到「博主」,因爲它在列表中位置較高(98與84使用)。 – 2010-12-01 05:52:16
我明白了!這就說得通了。 – 2010-12-03 04:14:43