rubyのベンチマーク-benchmark.rb-
rubyスクリプト中の特定の処理の実行時間を知りたいと思ったことはありませんか?(ありまーす!)
ということでbenchmark.rb
です。benchmark.rbを使用することで特定ブロックの実行時間を計測することができます。使い方はこんな感じ。
require 'benchmark' Benchmark.bm do |x| x.report do 10000.times do str = "test" end end end #=> user system total real 0.016000 0.000000 0.016000 ( 0.016000)
sqlite3とArrayのパフォーマンスを比べてみる
僕はとあるアプリでsqlite3を使ってデータを保存しています。sqlの行数は200行です。しかしデータを取り出すときはsqlの全てのデータを配列に入れてから、rubyの構文を使ってデータを取り出しています。なぜなら
からです。つまり**根拠のない理由**です。今回は僕の理由を検証するためbenchmark.rbを使ってsqlite3とArrayのパフォーマンスを計測してみることにしました。
require 'sqlite3' require 'benchmark' @arr_entry = Array.new dbfile = "newsing.db" @db = SQLite3::Database.new(dbfile) @db.execute('select * from entry_tbl') do |row| @arr_entry << row end n = 10 # 単純実行 Benchmark.bm do |x| # SQL x.report("sql:") do n.times do @db.execute('select * from entry_tbl') do |row| end end end # 配列 x.report("arr:") do n.times do @arr_entry.each do |elem| end end end end n = 1000 # 条件指定 Benchmark.bm do |x| # SQL x.report("sql_where:") do n.times do @db.execute(%Q[select * from entry_tbl where url = 'http']) do |row| end end end # 配列 x.report("arr_if:") do n.times do @arr_entry.each do |elem| if elem[0] == "http" end end end end end #=> user system total real sql: 0.906000 0.000000 0.906000 ( 0.906000) arr: 0.000000 0.000000 0.000000 ( 0.016000) user system total real sql_where: 0.250000 0.031000 0.281000 ( 0.328000) arr_if: 0.532000 0.000000 0.532000 ( 0.531000)
単純実行の場合は配列の方が圧倒的に早かったですが、条件を指定するとSQLの方が早いです。今回は200行ですが、行数が多くなればもっと明確な差が出るかもしれません。
SQLの場合はブロックに渡す前のSQL文の実行で絞込みが終わっているのに対し、配列は取りあえず全てをブロックに渡しているからでしょう。全てに要素を取り出してif文実行すりゃ遅くなりますよね。配列もブロックに渡す前に何らかの方法で削ればいいのですが、多元配列の場合は条件指定が難しくそれこそSQL文覚えた方がよいと思います。
ということで、配列からデータを取り出している僕のアプリは見直しが必要ということが分かりました。今はアクセス数が少ないですが、将来的にはパフォーマンスを改善したいところです。