Wann hast Du das letzte mal die Bibliothek benchmark aus der Ruby Standardbibliothek benutzt? Kannst Du Dich noch erinnern, wie die Methoden heißen, die man braucht, um einen Benchmarkbericht zu erzeugen?
Ich muss jedes mal neu in der API-Dokumentation nachschauen, weil die Bibliothek für mich nicht gerade intuitiv ist, so dass ich die Benutzung immer wieder vergesse. Aber dem kann man ja Abhilfe schaffen…
So ist Bench entstanden, eine kleine DSL um die benchmark-Bibliothek.
Installiert wird das ganze wie gewohnt mit: gem install bench bzw. sudo gem install bench.
So, wie funktioniert das nun? Es gibt nur zwei neue Kommandos: benchmark und run. Mit dem ersten definiert man ein neues Benchmark-Sample und mit run werden die Benchmarks dann durchgeführt und der bekannte Report ausgegeben.
Beispiel (adaptiert aus dem Beispiel aus der Pickaxe 2. Auflage S. 657):require 'bench' string = 'Stormy Weather' m = string.method(:length) benchmark 'code' do m.call end benchmark 'send' do string.send(:length) end benchmark 'eval' do eval "string.length" end run 10_000
user system total real code 0.020000 0.000000 0.020000 ( 0.015588) send 0.010000 0.000000 0.010000 ( 0.015256) eval 0.030000 0.010000 0.040000 ( 0.055029)
Ich finde den Code wesentlich einfacher als das Original, aber das ist sicherlich Geschmackssache. ;-)
Mit Bench sind auch interaktive Benchmarks in irb kein Problem:>> require 'bench' >> benchmark 'simple' do >> /ll/ =~ 'hello world' >> end >> benchmark 'freezed' do >> /ll/.freeze =~ 'hello world' >> end >> run 1000 user system total real simple 0.000000 0.000000 0.000000 ( 0.003960) freezed 0.010000 0.000000 0.010000 ( 0.004870) >> run 1000 user system total real simple 0.010000 0.000000 0.010000 ( 0.003969) freezed 0.000000 0.000000 0.000000 ( 0.004624) >> # Machen wir mehr Iterationen >> run 10000 user system total real simple 0.060000 0.000000 0.060000 ( 0.058049) freezed 0.060000 0.000000 0.060000 ( 0.058636) >> run 100000 user system total real simple 0.500000 0.000000 0.500000 ( 0.502427) freezed 0.540000 0.000000 0.540000 ( 0.533421) >> # Fügen wir ein weiteres Benchmark-Sample hinzu >> RE = /ll/ >> benchmark 'constant' do >> RE =~ 'hello world' >> end >> run 100000 user system total real simple 0.510000 0.000000 0.510000 ( 0.504704) freezed 0.530000 0.000000 0.530000 ( 0.536948) constant 0.560000 0.000000 0.560000 ( 0.554470)
Man kann also run auch mehrfach hintereinander aufrufen, um statistische Ausreißer in den ermittelten Zeiten zu indentifizieren. Außerdem kann man run mit unterschiedlichen Werten für die Iterationen aufrufen, um aussagekräftigere Ergebnisse zu erzielen.
Der eigentliche Code für die DSL ist recht simpel und kurz:require 'benchmark' module Bench # Create a new benchmark sample <tt>name</tt>. # Within the block you specify the code to execute. def benchmark name, &block bm = { 'name' => name, 'code' => block } Bench.queue << bm "#{Bench.queue.size} benchmark samples" # nice return for use with irb ;) end # Runs the benchmarks. Parameter <tt>count</tt> is the number of iterations # each sample code should be repeated. def run count=1 label_width = Bench.queue.inject(0) {|max, bm| len = bm['name'].length; len > max ? len : max} Benchmark.bm(label_width) do |x| Bench.queue.each do |bm| name, code = bm['name'], bm['code'] x.report(name) { count.times(&code) } end end end module_function :benchmark, :run @queue = [] class << self attr_reader :queue end end include Bench
Gehostet wird die jeweils aktuelle Version des Codes auf Gitorious. Außerdem ist Bench auf Rubyforge zu finden.
EDIT: Code aktualisiert.
Kommentar schreiben
Kommentare
Schöne Sache. Ich find Benchmark jetzt nicht unbedingt soo kompliziert, dass ich da dringend auf so ein Programm gewartet habe. Aber die Vereinfachung ist sehr praktisch. Mich hats immer aufgeregt wenn ich in der irb ein Benchmark-Block mit etlichen Reports geschrieben habe und im letzten Report dann durch Verklicken ein Syntax-Error entstand ^^°
Ui, das ist nett. Zeigt doch nochmal wie einfach es (anscheinend) ist mit Ruby sich seine Welt/Arbeitsumgebung einfach anzupassen...
Seltsame...warum hat er nicht einfach alles unter class << self gestellt?
"murphy: "Seltsame...warum hat er nicht einfach alles unter class << self gestellt?"
Was meinst Du?