2012-03-09 18 views
0

ブロック内で多くのメソッドを実行し、実行に要した時間を記録し、後で参照できるようにその情報をデータベースに送信するベンチマークのラッピングが含まれています。 。これは非常に醜いコードになります。ベンチマーク用のRubyメタプログラミング

benchmark_data = Benchmark.realtime do 
    begin 
    do_something() 
    rescue StandardError => e 
    log_errors("error occurred") 
    raise e 
    end 
end 

write_benchmark_data_to_db(benchmark_data) 

このコードは、基本的にはベンチマークするすべての関数の周りにコピーされます。メタプログラミングを使用してより良い方法がありますか?私はベンチマークコードをすべてクラスの外に保ち、メソッドの測定をしたいと思います。

私は、誰もが任意のアイデアを持っています

class Foo 
    def a() 
    puts "A" 
    end 
    ... #repeat for b,c,d,e... 
end 

f = Foo.new() 

add_benchmark(f, [:a,:b,:d]) #records a benchmark event each time f.a,f.b, and f.d are called 

を考えていましたか?可能であれば、Fooのサブクラスを使用しないでください。ベンチマークが必要なすべてのオブジェクトにサブクラスが必要になるからです。ここで

+0

ベンチマークでコール全体を実行しないと、各メソッドで費やされた時間の内訳が分かりますか? –

答えて

0

は1つの慣用Rubyのソリューションです:この猿 - パッチはModule

class Module 
    def method_bmark_database(*syms) 
    syms.each do |sym| 
     old=instance_method(sym) 
     define_method(sym) do |*args| 
     benchmark_data = Benchmark.realtime do 
      begin 
      old.call(*args) 
      rescue StandardError => e 
      log_errors("error occurred") 
      raise e 
      end 
     end 
     write_benchmark_data_to_db(benchmark_data) 
     end 
    end 
    end 
end 

が、あなたは常にそれを置くことができます:ここで

def with_stored_benchmark(&block) 
    benchmark_data = Benchmark.realtime do 
    begin 
     block.call 
    rescue StandardError => e 
     log_errors("error occurred") 
     raise e 
    end 
    end 
    write_benchmark_data_to_db(benchmark_data) 
end 

は(種類の)別のソリューションですモジュールに組み込み、それを組み込みます。今はRubyを使っているコンピュータではないので、私はうまく動作しているとは思えませんが、それは私には似ています。

また

、あなたがベンチマークしているオブジェクトを選択する場合:あなたは

class Object 
    alias :old_method_missing :method_missing 
    def method_missing(meth, *args, &block) 
    if benchmark_method? meth 
     begin 
     old_method_missing meth, *args, &block 
     rescue Exception => e 
     log_errors("...") 
     raise e 
     end 
    else old_method_missing meth, *args, &block 
    end 
    end 
end 

ような何かをしないなぜ私はそれは一目瞭然だ

def log_performance_to_DB(obj, *methods) 
    methods.each do |m| 
    old=obj.method(m) 
    obj.define_singleton_method(m) do |*args| 
     benchmark_data = Benchmark.realtime do 
     begin 
      old.call(*args) 
     rescue StandardError => e 
      log_errors("error occurred") 
      raise e 
     end 
     end 
     write_benchmark_data_to_db(benchmark_data) 
    end 
    end 
end 
+0

「収穫」は「yeild」ではありません。ブロックが明白であればおそらくいいかもしれません。 –

+0

これはちょっとだけ上手くいくと思います。私はまだwith_stored_benchmark()ですべてのメソッド呼び出しをラップしなければならず、コード内で多くのコピー/ペーストを行い、誰かがこの関数でラップするのを忘れてしまう可能性があります。私はこれを自動的に行う方法を探しています。 –

+0

@BillWilliamson:私は編集し、答えに2つの他のソリューションを追加しました。これらはあなたが望むものですか? – Linuxios

0

と思います。たぶん私はあなたが本当に意味することを理解していなかった...