2011-06-27 64 views
11

同步記錄會導致較大的性能損失,因爲它可能會阻塞。是否有一個獨立的Ruby庫進行異步日誌記錄(log4r似乎不)?我可以修改標準庫記錄器以異步記錄嗎?我正在尋找類似log4j的AsyncAppender之類的東西 - 但最好是一個利用Ruby的代碼塊將盡可能多的工作轉移到後臺線程的實現。是否有Ruby的異步日誌記錄庫?

+0

是'ruby'解釋這些天仍然相當火腿串成時它涉及到多線程代碼?是否還有一個巨大的解釋器鎖,它是基本的單線程本地Ruby代碼?我很好奇,因爲除非你已經使用像[eventmachine](http://rubyeventmachine.com/)這樣的框架來強制你的IO是異步的,否則你可能實際上並沒有看到只做日誌異步的好處。 – sarnold

+0

我通常使用JRuby,所以有真正的Java線程(我認爲)... –

+0

ooh;)那麼這是一個令人信服的理由來考慮使用JRuby,然後。謝謝。 – sarnold

回答

15

我知道你真的不應該回答你自己的問題,但似乎一切都容易紅寶石:

require 'thread' 
require 'singleton' 
require 'delegate' 
require 'monitor' 

class Async 
    include Singleton 

    def initialize 
    @queue = Queue.new 
    Thread.new { loop { @queue.pop.call } } 
    end 

    def run(&blk) 
    @queue.push blk 
    end 
end 

class Work < Delegator 
    include MonitorMixin 

    def initialize(&work) 
    super work; @work, @done, @lock = work, false, new_cond 
    end 

    def calc 
    synchronize { 
     @result, @done = @work.call, true; 
     @lock.signal 
    } 
    end 

    def __getobj__ 
    synchronize { @lock.wait_while { [email protected] } } 
    @result 
    end 
end 

Module.class.class_exec { 
    def async(*method_names) 
    method_names.each do |method_name| 
     original_method = instance_method(method_name) 
     define_method(method_name) do |*args,&blk| 
     work = Work.new { original_method.bind(self).call(*args,&blk) } 
     Async.instance.run { work.calc } 
     return work 
     end 
    end 
    end 
} 

而對於我的日誌例子:

require 'Logger' 
class Logger 
    async :debug 
end 
log = Logger.new STDOUT 
log.debug "heloo" 

作爲返回值工作,你可以用這個幾乎任何東西:

require "test/unit" 
class ReturnValues < Test::Unit::TestCase 
    def do_it 
    5 + 7 
    end 
    async :do_it 
    def test_simple 
    assert_equal 10, do_it - 2 
    end 
end 
+0

非常好。 Ruby的表現力讓我驚歎不已。你提到過使用JRuby,所以你可能有真正的線程,但你也使用了很多動態ruby魔術,所以JRuby如何處理所有動態技巧?與JRuby和MRI並肩觀看一些基準會很酷。 – davidk01

+0

不錯的代碼!使用光纖/事件機器可能會更好。線程將完成這項工作,但它們在覈磁共振(以及未來的JRuby)中要重得多,需要管理和同步。我認爲已經有一個事件機器文件流可能接近你想要的:http://stackoverflow.com/questions/2749503/what-is-the-best-way-to-read-files-in-an -eventmachine-based- –

2

沒有親身經歷與:

的Swiftcore Analogger實現了Ruby程序快速異步日誌系統 以及爲 發送日誌消息客戶端庫類比過程。

Analogger將接受來自多個來源的日誌,並且可以有多個 日誌記錄目標。目前,支持將日誌記錄到文件,STDOUT或 STDERR。未來版本也可能支持登錄到數據庫目標。

模擬器依賴於EventMachine(http://rubyforge.org/projects/eventmachine) 來提供網絡通信的框架,儘管EM不是用於客戶端庫的 。

+0

這似乎在一個單獨的進程中完成異步日誌記錄 - 我更喜歡進程內日誌記錄(只在不同的線程上) –

1

在Logger類的內置已經是線程安全的

+0

我想將日誌消息寫到磁盤上的一個單獨的線程中,所以如果IO阻塞它不會減慢我的主線程。 –