Home

Title

Code Listing: stat_bench.rb

# benchmark to test if File.directory? first is faster than
# Dir.entries followed by catching and raising an exception.

require 'benchmark'

include Benchmark

def entries_with_exception(dir)
  Dir.entries(dir).size
rescue Errno::ENOENT
  0
end

def entries_after_stat(dir)
  if File.directory?(dir)
    Dir.entries(dir).size
  else
    0
  end
end

def entries(dirs, method, opts = {})
  # drop disk cache on Linux
  `sync && echo 3 | sudo tee /proc/sys/vm/drop_caches` if opts[:drop_cache]

  dirs.inject(0) do |sum, dir|
    sum + send(method, dir)
  end
end

def compare(dirs, opts = {}) # dirs, n = 6, drop_cache = false)
  n = opts[:n] || 6

  benchmark(CAPTION, 10, FORMAT, '>excep avg', '>stat avg') do |x|
    e_timings = []                # with_exception timings
    s_timings = []                # after_stat timings
    
    n.times do
      e_timings << x.report('excep')  { entries(dirs, :entries_with_exception, opts) }
      s_timings << x.report('stat ')  { entries(dirs, :entries_after_stat, opts) }
    end

    [e_timings.inject(&:+)/n, s_timings.inject(&:+)/n]
  end
end

root = '/usr/lib'
dirs = `find #{root} -type d`.split($/).shuffle
no_dirs = dirs.map{|d| d + 'nope'}

puts '=== warming up ==='
20.times do
  entries(dirs, :entries_with_exception)
  entries(no_dirs, :entries_with_exception)
  entries(dirs, :entries_after_stat)
  entries(no_dirs, :entries_after_stat)
end

puts "=== testing with #{dirs.length} dirs in #{root} ==="
compare(dirs)
puts '=== now with non-existent directories ==='
compare(no_dirs)

puts '=== drop the disk cache ==='
compare(dirs, :drop_cache => true)
puts '=== now with non-existent directories ==='
compare(no_dirs, :drop_cache => true)

Ruby 1.9.3-p194 raw data

=== warming up ===
=== testing with 2449 dirs in /usr/lib ===
                 user     system      total        real
excep        0.030000   0.040000   0.070000 (  0.069843)
stat         0.050000   0.030000   0.080000 (  0.078254)
excep        0.030000   0.040000   0.070000 (  0.071451)
stat         0.040000   0.030000   0.070000 (  0.077277)
excep        0.030000   0.050000   0.080000 (  0.069525)
stat         0.030000   0.050000   0.080000 (  0.079875)
excep        0.010000   0.050000   0.060000 (  0.069462)
stat         0.020000   0.050000   0.070000 (  0.077389)
excep        0.020000   0.050000   0.070000 (  0.069943)
stat         0.030000   0.050000   0.080000 (  0.079212)
excep        0.030000   0.040000   0.070000 (  0.069370)
stat         0.010000   0.070000   0.080000 (  0.078848)
>excep avg   0.025000   0.045000   0.070000 (  0.069932)
>stat avg    0.030000   0.046667   0.076667 (  0.078476)
=== now with non-existent directories ===
                 user     system      total        real
excep        0.080000   0.010000   0.090000 (  0.088597)
stat         0.010000   0.000000   0.010000 (  0.007701)
excep        0.080000   0.000000   0.080000 (  0.090979)
stat         0.000000   0.010000   0.010000 (  0.007933)
excep        0.080000   0.010000   0.090000 (  0.090116)
stat         0.010000   0.000000   0.010000 (  0.007656)
excep        0.090000   0.000000   0.090000 (  0.089195)
stat         0.000000   0.010000   0.010000 (  0.007738)
excep        0.080000   0.010000   0.090000 (  0.091830)
stat         0.000000   0.010000   0.010000 (  0.007665)
excep        0.080000   0.010000   0.090000 (  0.089698)
stat         0.010000   0.000000   0.010000 (  0.007713)
>excep avg   0.081667   0.006667   0.088333 (  0.090069)
>stat avg    0.005000   0.005000   0.010000 (  0.007734)
=== drop the disk cache ===
                 user     system      total        real
excep        0.090000   0.250000   0.460000 ( 12.241728)
stat         0.110000   0.200000   0.380000 ( 11.444665)
excep        0.070000   0.270000   0.410000 ( 11.554205)
stat         0.100000   0.210000   0.390000 ( 11.102887)
excep        0.080000   0.260000   0.410000 ( 12.195852)
stat         0.110000   0.190000   0.370000 ( 11.511162)
excep        0.090000   0.260000   0.430000 ( 12.495996)
stat         0.090000   0.220000   0.390000 ( 10.402701)
excep        0.100000   0.230000   0.410000 ( 11.645824)
stat         0.100000   0.210000   0.380000 ( 10.886361)
excep        0.090000   0.250000   0.410000 ( 12.645786)
stat         0.090000   0.220000   0.380000 ( 10.524727)
>excep avg   0.086667   0.253333   0.421667 ( 12.129898)
>stat avg    0.100000   0.208333   0.381667 ( 10.978750)
=== now with non-existent directories ===
                 user     system      total        real
excep        0.180000   0.120000   0.380000 (  4.878866)
stat         0.010000   0.100000   0.180000 (  5.034120)
excep        0.190000   0.110000   0.370000 (  5.225184)
stat         0.010000   0.100000   0.160000 (  4.865224)
excep        0.200000   0.080000   0.350000 (  4.906489)
stat         0.010000   0.080000   0.150000 (  4.834200)
excep        0.220000   0.080000   0.370000 (  4.748225)
stat         0.020000   0.080000   0.160000 (  4.565369)
excep        0.210000   0.100000   0.390000 (  5.325185)
stat         0.020000   0.090000   0.180000 (  5.298778)
excep        0.210000   0.080000   0.360000 (  4.925327)
stat         0.010000   0.090000   0.160000 (  4.842326)
>excep avg   0.201667   0.095000   0.370000 (  5.001546)
>stat avg    0.013333   0.090000   0.165000 (  4.906669)

JRuby 1.7.0 raw data

=== testing with 2449 dirs in /usr/lib ===
                 user     system      total        real
excep        0.130000   0.050000   0.180000 (  0.165000)
stat         0.150000   0.090000   0.240000 (  0.226000)
excep        0.100000   0.070000   0.170000 (  0.163000)
stat         0.140000   0.040000   0.180000 (  0.183000)
excep        0.110000   0.040000   0.150000 (  0.160000)
stat         0.110000   0.080000   0.190000 (  0.181000)
excep        0.120000   0.030000   0.150000 (  0.156000)
stat         0.090000   0.090000   0.180000 (  0.182000)
excep        0.130000   0.030000   0.160000 (  0.159000)
stat         0.100000   0.070000   0.170000 (  0.181000)
excep        0.110000   0.050000   0.160000 (  0.157000)
stat         0.130000   0.050000   0.180000 (  0.181000)
>excep avg   0.116667   0.045000   0.161667 (  0.160000)
>stat avg    0.120000   0.070000   0.190000 (  0.189000)
=== now with non-existent directories ===
                 user     system      total        real
excep        1.570000   0.020000   1.590000 (  0.918000)
stat         0.020000   0.010000   0.030000 (  0.032000)
excep        0.710000   0.000000   0.710000 (  0.689000)
stat         0.030000   0.010000   0.040000 (  0.026000)
excep        0.680000   0.020000   0.700000 (  0.695000)
stat         0.020000   0.000000   0.020000 (  0.016000)
excep        0.650000   0.010000   0.660000 (  0.667000)
stat         0.010000   0.000000   0.010000 (  0.015000)
excep        0.730000   0.010000   0.740000 (  0.677000)
stat         0.010000   0.010000   0.020000 (  0.016000)
excep        0.660000   0.010000   0.670000 (  0.666000)
stat         0.000000   0.010000   0.010000 (  0.016000)
>excep avg   0.833333   0.011667   0.845000 (  0.718667)
>stat avg    0.015000   0.006667   0.021667 (  0.020167)
=== drop the disk cache ===
                 user     system      total        real
excep        0.600000   0.320000   1.300000 ( 15.008000)
stat         0.430000   0.290000   0.800000 ( 12.328000)
excep        0.610000   0.330000   1.030000 ( 12.377000)
stat         0.870000   0.340000   1.300000 ( 12.411000)
excep        0.560000   0.300000   0.940000 ( 11.877000)
stat         0.480000   0.350000   0.930000 ( 12.946000)
excep        0.370000   0.260000   0.720000 ( 12.027000)
stat         0.470000   0.340000   0.890000 ( 12.719000)
excep        0.350000   0.300000   0.730000 ( 14.082000)
stat         0.420000   0.320000   0.840000 ( 14.975000)
excep        0.290000   0.410000   0.800000 ( 12.136000)
stat         0.400000   0.290000   0.770000 ( 12.154000)
>excep avg   0.463333   0.320000   0.920000 ( 12.917833)
>stat avg    0.511667   0.321667   0.921667 ( 12.922167)
=== now with non-existent directories ===
                 user     system      total        real
excep        1.600000   0.130000   1.820000 (  7.417000)
stat         0.060000   0.130000   0.270000 (  5.766000)
excep        1.720000   0.180000   1.970000 (  7.100000)
stat         0.110000   0.090000   0.270000 (  6.099000)
excep        1.640000   0.150000   1.870000 (  7.107000)
stat         0.070000   0.110000   0.250000 (  5.497000)
excep        1.630000   0.120000   1.830000 (  6.859000)
stat         0.060000   0.140000   0.270000 (  5.542000)
excep        1.780000   0.150000   1.990000 (  7.237000)
stat         0.080000   0.110000   0.270000 (  5.483000)
excep        1.490000   0.150000   1.730000 (  7.019000)
stat         0.070000   0.110000   0.240000 (  5.280000)
>excep avg   1.643333   0.146667   1.868333 (  7.123167)
>stat avg    0.075000   0.115000   0.261667 (  5.611167)