viiite 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/CHANGELOG.md +70 -0
  2. data/Gemfile +2 -9
  3. data/Gemfile.lock +11 -32
  4. data/README.md +42 -123
  5. data/examples/bench_attr_vs_method-1.8.7.jpeg +0 -0
  6. data/examples/bench_attr_vs_method-1.9.3.jpeg +0 -0
  7. data/examples/bench_attr_vs_method.rb +18 -0
  8. data/examples/bench_iteration.rb +2 -4
  9. data/examples/bench_sort.rb +2 -7
  10. data/lib/viiite.rb +40 -18
  11. data/lib/viiite/bdb.rb +28 -0
  12. data/lib/viiite/bdb/cached.rb +63 -0
  13. data/lib/viiite/bdb/immediate.rb +46 -0
  14. data/lib/viiite/bdb/utils.rb +16 -0
  15. data/lib/viiite/benchmark.rb +35 -0
  16. data/lib/viiite/benchmark/runner.rb +50 -0
  17. data/lib/viiite/command.rb +33 -2
  18. data/lib/viiite/command/commons.rb +22 -0
  19. data/lib/viiite/command/help.rb +4 -5
  20. data/lib/viiite/command/plot.rb +44 -44
  21. data/lib/viiite/command/plot/to_gnuplot.rb +65 -0
  22. data/lib/viiite/command/{graph_style.rash → plot/to_gnuplot_graph.rash} +0 -0
  23. data/lib/viiite/command/{serie_style.rash → plot/to_gnuplot_serie.rash} +0 -0
  24. data/lib/viiite/command/plot/to_highcharts.rb +38 -0
  25. data/lib/viiite/command/plot/to_highcharts_graph.rb +29 -0
  26. data/lib/viiite/command/plot/to_text.rb +30 -0
  27. data/lib/viiite/command/report.rb +32 -10
  28. data/lib/viiite/command/run.rb +30 -7
  29. data/lib/viiite/errors.rb +5 -0
  30. data/lib/viiite/loader.rb +2 -2
  31. data/lib/viiite/tms.rb +21 -31
  32. data/lib/viiite/version.rb +5 -5
  33. data/spec/fixtures/bdb/Array/bench_sort.rb +7 -0
  34. data/spec/fixtures/{bench_iteration.rb → bdb/bench_iteration.rb} +2 -4
  35. data/spec/fixtures/command/bench_iteration.rb +3 -0
  36. data/spec/fixtures/saved/Array/bench_sort.rash +12 -0
  37. data/spec/fixtures/saved/bench_iteration.rash +18 -0
  38. data/spec/integration/plot/plot_1.cmd +1 -0
  39. data/spec/integration/plot/plot_1.stdout +64 -0
  40. data/spec/integration/plot/plot_2.cmd +1 -0
  41. data/spec/integration/plot/plot_2.stdout +37 -0
  42. data/spec/integration/plot/plot_3.cmd +1 -0
  43. data/spec/integration/plot/plot_3.stdout +64 -0
  44. data/spec/integration/plot/plot_4.cmd +1 -0
  45. data/spec/integration/plot/plot_4.stdout +1 -0
  46. data/spec/integration/report/viiite_report_1.cmd +1 -1
  47. data/spec/integration/report/viiite_report_1.stdout +7 -7
  48. data/spec/integration/report/viiite_report_2.cmd +1 -1
  49. data/spec/integration/report/viiite_report_2.stdout +22 -10
  50. data/spec/integration/report/viiite_report_3.cmd +1 -1
  51. data/spec/integration/report/viiite_report_3.stdout +46 -18
  52. data/spec/integration/report/viiite_report_4.cmd +1 -1
  53. data/spec/integration/report/viiite_report_4.stdout +34 -22
  54. data/spec/integration/report/viiite_report_5.cmd +1 -0
  55. data/spec/integration/report/viiite_report_5.stdout +7 -0
  56. data/spec/integration/report/viiite_report_6.cmd +1 -0
  57. data/spec/integration/report/viiite_report_6.stdout +7 -0
  58. data/spec/integration/report/viiite_report_7.cmd +1 -0
  59. data/spec/integration/report/viiite_report_7.stdout +7 -0
  60. data/spec/integration/report/viiite_report_8.cmd +1 -0
  61. data/spec/integration/report/viiite_report_8.stdout +16 -0
  62. data/spec/integration/report/viiite_report_9.cmd +1 -0
  63. data/spec/integration/report/viiite_report_9.stdout +88 -0
  64. data/spec/integration/test_command.rb +19 -23
  65. data/spec/integration/viiite/viiite_help.stdout +6 -0
  66. data/spec/spec_helper.rb +11 -17
  67. data/spec/unit/bdb/cached/test_dataset.rb +68 -0
  68. data/spec/unit/bdb/immediate/test_benchmark.rb +31 -0
  69. data/spec/unit/bdb/immediate/test_dataset.rb +31 -0
  70. data/spec/unit/bdb/immediate/test_enumerable.rb +20 -0
  71. data/spec/unit/bdb/immediate/test_pattern.rb +25 -0
  72. data/spec/unit/bdb/test_new.rb +44 -0
  73. data/spec/unit/bdb/utils/test_bench_file.rb +24 -0
  74. data/spec/unit/bdb/utils/test_replace_extension.rb +21 -0
  75. data/spec/unit/benchmark/bench_add.rb +3 -0
  76. data/spec/unit/benchmark/test_new.rb +28 -0
  77. data/spec/unit/command/commons/existing.rash +1 -0
  78. data/spec/unit/command/commons/test_single_source.rb +64 -0
  79. data/spec/unit/{formatter/plot → command/plot/gnuplot_utils}/test_to_data.rb +4 -4
  80. data/spec/unit/{formatter/plot → command/plot/gnuplot_utils}/test_to_dataset.rb +5 -5
  81. data/spec/unit/{formatter/plot → command/plot/gnuplot_utils}/test_to_plot.rb +4 -4
  82. data/spec/unit/command/test_run.rb +25 -12
  83. data/spec/unit/{test_runner.rb → test_benchmark.rb} +30 -11
  84. data/spec/unit/test_viiite.rb +17 -4
  85. data/spec/unit/tms/test_attributes.rb +11 -0
  86. data/spec/unit/tms/test_coerce.rb +11 -23
  87. data/spec/unit/tms/test_conversions.rb +23 -0
  88. data/spec/unit/tms/test_operations.rb +22 -0
  89. data/tasks/clean.rake +1 -1
  90. data/tasks/debug_mail.rake +13 -13
  91. data/tasks/gem.rake +13 -13
  92. data/tasks/integration_test.rake +3 -3
  93. data/tasks/spec_test.rake +9 -9
  94. data/tasks/unit_test.rake +9 -10
  95. data/tasks/yard.rake +13 -13
  96. data/viiite.gemspec +26 -29
  97. data/viiite.noespec +4 -7
  98. metadata +335 -235
  99. data/examples/bench_sort.eps +0 -816
  100. data/examples/bench_sort.rash +0 -100
  101. data/examples/raw.rash +0 -6
  102. data/lib/viiite/formatter.rb +0 -5
  103. data/lib/viiite/formatter/plot.rb +0 -38
  104. data/lib/viiite/runner.rb +0 -59
  105. data/lib/viiite/viiite_file.rb +0 -20
  106. data/spec/integration/raw_data.rash +0 -6
  107. data/spec/unit/tms/test_divide.rb +0 -26
  108. data/spec/unit/tms/test_minus.rb +0 -26
  109. data/spec/unit/tms/test_plus.rb +0 -34
  110. data/spec/unit/tms/test_times.rb +0 -26
  111. data/spec/unit/tms/test_to_a.rb +0 -11
  112. data/spec/unit/tms/test_to_ruby_literal.rb +0 -11
  113. data/spec/unit/tms/test_to_s.rb +0 -11
@@ -0,0 +1,28 @@
1
+ require 'fileutils'
2
+ require 'viiite/bdb/utils'
3
+ require 'viiite/bdb/immediate'
4
+ require 'viiite/bdb/cached'
5
+ module Viiite
6
+ class BDB
7
+ include Utils
8
+
9
+ DEFAULT_OPTIONS = {
10
+ :folder => "benchmarks",
11
+ :cache => true,
12
+ :cache_mode => "w",
13
+ :pattern => "**/*.rb",
14
+ }
15
+
16
+ def self.new(options = {})
17
+ options = DEFAULT_OPTIONS.merge(options)
18
+ folder = options[:folder]
19
+ bdb = BDB::Immediate.new(folder, options[:pattern])
20
+ if cache = options[:cache]
21
+ cache = File.join(folder, '.cache') unless cache.is_a?(String)
22
+ bdb = BDB::Cached.new(bdb, cache, options[:cache_mode])
23
+ end
24
+ bdb
25
+ end
26
+
27
+ end # class BDB
28
+ end # module Viiite
@@ -0,0 +1,63 @@
1
+ module Viiite
2
+ class BDB
3
+ class Cached < SimpleDelegator
4
+ include Utils
5
+
6
+ attr_reader :cache_folder
7
+ attr_reader :cache_mode
8
+
9
+ def initialize(delegate, cache_folder, cache_mode = "w")
10
+ super delegate
11
+ @cache_folder = cache_folder
12
+ @cache_mode = cache_mode
13
+ end
14
+
15
+ def cached?
16
+ true
17
+ end
18
+
19
+ def benchmark(name)
20
+ bench = super(name)
21
+ cache = cache_file(name)
22
+ Proxy.new(bench, cache, cache_mode)
23
+ end
24
+
25
+ def dataset(name)
26
+ if File.exists?(cache_file = cache_file(name))
27
+ Alf::Reader.reader(cache_file, self)
28
+ else
29
+ benchmark(name)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def cache_file(name)
36
+ bench_file(cache_folder, name, ".rash")
37
+ end
38
+
39
+ class Proxy < DelegateClass(Benchmark)
40
+ include Alf::Iterator
41
+
42
+ def initialize(benchmark, cache_file, cache_mode)
43
+ @benchmark = benchmark
44
+ @cache_file = cache_file
45
+ @cache_mode = cache_mode
46
+ super(@benchmark)
47
+ end
48
+
49
+ def each
50
+ FileUtils.mkdir_p(File.dirname(@cache_file))
51
+ File.open(@cache_file, @cache_mode) do |io|
52
+ @benchmark.each do |tuple|
53
+ io << Alf::Tools.to_ruby_literal(tuple) << "\n"
54
+ yield(tuple)
55
+ end
56
+ end
57
+ end
58
+
59
+ end # class Proxy
60
+
61
+ end # class Cached
62
+ end # class BDB
63
+ end # module Viiite
@@ -0,0 +1,46 @@
1
+ module Viiite
2
+ class BDB
3
+ class Immediate
4
+ include Utils
5
+ include Alf::Iterator
6
+
7
+ attr_reader :folder
8
+
9
+ def initialize(folder, pattern = DEFAULT_OPTIONS[:pattern])
10
+ @folder = folder
11
+ if pattern =~ /(\.\w+)$/
12
+ @pattern = pattern
13
+ @ext = $1
14
+ else
15
+ raise InvalidPattern, "The benchmark suite pattern must end with a unique extension " <<
16
+ "(for deducing benchmark file from name): #{pattern}"
17
+ end
18
+ end
19
+
20
+ def each
21
+ Dir[File.join(folder, @pattern)].each do |f|
22
+ yield(:name => f[1+folder.size..-1-@ext.size], :file => f)
23
+ end
24
+ end
25
+
26
+ def cached?
27
+ false
28
+ end
29
+
30
+ def benchmark(name)
31
+ if File.exists?(file = bench_file(folder, name.to_s, @ext))
32
+ return Alf::Reader.reader(file, self)
33
+ else
34
+ raise NoSuchBenchmarkError, "No such benchmark #{name}"
35
+ end
36
+ end
37
+
38
+ def dataset(name)
39
+ benchmark(name)
40
+ rescue NoSuchBenchmarkError => ex
41
+ raise Alf::NoSuchDatasetError, ex.message, ex.backtrace
42
+ end
43
+
44
+ end # class Immediate
45
+ end # class BDB
46
+ end # module Viiite
@@ -0,0 +1,16 @@
1
+ module Viiite
2
+ class BDB
3
+ module Utils
4
+
5
+ def replace_extension(file, ext)
6
+ old_ext = File.extname(file)
7
+ "#{file[0..-(1+old_ext.size)]}#{ext}"
8
+ end
9
+
10
+ def bench_file(folder, name, ext)
11
+ File.join(folder, replace_extension(name, ext))
12
+ end
13
+
14
+ end # module Utils
15
+ end # class BDB
16
+ end # module Viiite
@@ -0,0 +1,35 @@
1
+ require 'viiite/benchmark/runner'
2
+ module Viiite
3
+ class Benchmark
4
+ include Runner
5
+ include Alf::Iterator
6
+
7
+ attr_reader :definition
8
+
9
+ def initialize(definition)
10
+ @definition = definition
11
+ end
12
+
13
+ @benchmarks = []
14
+ def self.new(arg, *others)
15
+ case arg
16
+ when String
17
+ load File.expand_path(arg)
18
+ @benchmarks.pop
19
+ when IO, StringIO
20
+ Kernel.eval(arg.read, TOPLEVEL_BINDING)
21
+ @benchmarks.pop
22
+ else
23
+ bench = super(arg)
24
+ @benchmarks << bench
25
+ bench
26
+ end
27
+ end
28
+
29
+ def each(&reporter)
30
+ self.dup._each(&reporter)
31
+ end
32
+
33
+ Alf::Reader.register(:viiite, [".viiite", ".rb"], self)
34
+ end # class Benchmark
35
+ end # module Viiite
@@ -0,0 +1,50 @@
1
+ module Viiite
2
+ class Benchmark
3
+ module Runner
4
+
5
+ def with(hash)
6
+ if block_given?
7
+ org_tuple = @tuple
8
+ @tuple = org_tuple.merge(hash)
9
+ res = yield
10
+ @tuple = org_tuple
11
+ res
12
+ else
13
+ @tuple.merge!(hash)
14
+ end
15
+ end
16
+
17
+ def range_over(range, name)
18
+ range.each do |value|
19
+ with(name => value){ yield value }
20
+ end
21
+ end
22
+
23
+ def variation_point(name, value, &proc)
24
+ with({name => value}, &proc)
25
+ end
26
+
27
+ def report(hash = {}, &block)
28
+ hash = {:bench => hash.to_sym} unless hash.is_a?(Hash)
29
+ with(hash) {
30
+ GC.start
31
+ tms = Viiite.measure(&block)
32
+ with(:tms => tms){ output }
33
+ }
34
+ end
35
+
36
+ protected
37
+
38
+ def _each(&reporter)
39
+ @tuple, @reporter = {}, reporter
40
+ self.instance_eval(&definition)
41
+ @tuple, @reporter = nil, nil
42
+ end
43
+
44
+ def output
45
+ @reporter.call @tuple.dup
46
+ end
47
+
48
+ end # module Runner
49
+ end # class Benchmark
50
+ end # module Viiite
@@ -21,7 +21,7 @@ module Viiite
21
21
 
22
22
  # Install options
23
23
  options do |opt|
24
- opt.on("-Idirectory",
24
+ opt.on("-Idirectory",
25
25
  "specify $LOAD_PATH directory (may be used more than once)") do |val|
26
26
  $LOAD_PATH.unshift val
27
27
  end
@@ -29,6 +29,32 @@ module Viiite
29
29
  "require the library, before executing viiite") do |lib|
30
30
  require(lib)
31
31
  end
32
+
33
+ @bdb_options = {}
34
+ opt.on('--suite=FOLDER',
35
+ "Specify the folder of the benchmark suite (defaults to 'benchmarks')") do |val|
36
+ unless File.directory?(val)
37
+ raise Quickl::InvalidArgument, "Missing folder #{val}"
38
+ end
39
+ @bdb_options[:folder] = val
40
+ end
41
+ opt.on('--pattern=GLOB',
42
+ "Specify the pattern to find benchmarks in the suite folder (defaults to '**/*.rb')") do |glob|
43
+ @bdb_options[:pattern] = glob
44
+ end
45
+ opt.on('--[no-]cache=[FOLDER]',
46
+ 'Specify the cache heuristic and folder (defaults to --cache)') do |folder|
47
+ @bdb_options[:cache] = folder
48
+ end
49
+ opt.on('--cache-mode=MODE',
50
+ 'Specify the exact mode for accessing cache files') do |mode|
51
+ @bdb_options[:cache_mode] = mode
52
+ end
53
+ opt.on('-a', '--append',
54
+ "Shortcut to --cache-mode=a"){ @bdb_options[:cache_mode] = 'a' }
55
+ opt.on('-w', '--write',
56
+ "Shortcut to --cache-mode=w"){ @bdb_options[:cache_mode] = 'w' }
57
+
32
58
  opt.on_tail("--help", "Show help") do
33
59
  raise Quickl::Help
34
60
  end
@@ -36,9 +62,14 @@ module Viiite
36
62
  raise Quickl::Exit, "viiite #{Viiite::VERSION} (c) 2011, Bernard Lambeau"
37
63
  end
38
64
  end
39
-
65
+
66
+ def bdb
67
+ @bdb ||= BDB.new(@bdb_options)
68
+ end
69
+
40
70
  end # class Command
41
71
  end # module Viiite
72
+ require "viiite/command/commons"
42
73
  require "viiite/command/help"
43
74
  require "viiite/command/run"
44
75
  require "viiite/command/report"
@@ -0,0 +1,22 @@
1
+ module Viiite
2
+ class Command
3
+ module Commons
4
+
5
+ def single_source(argv)
6
+ raise Quickl::InvalidArgument if argv.size > 1
7
+ if arg = argv.first
8
+ if File.exists?(arg.to_s)
9
+ Alf::Reader.reader(arg.to_s)
10
+ elsif requester && requester.respond_to?(:bdb)
11
+ block_given? ? yield(requester.bdb, arg) : requester.bdb.dataset(arg)
12
+ else
13
+ raise Quickl::InvalidArgument, "Missing benchmark #{arg}"
14
+ end
15
+ else
16
+ Alf::Reader.reader($stdin)
17
+ end
18
+ end
19
+
20
+ end # module Commons
21
+ end # class Command
22
+ end # module Viiite
@@ -1,24 +1,23 @@
1
1
  module Viiite
2
2
  class Command
3
- #
3
+ #
4
4
  # Show help about a specific command
5
5
  #
6
6
  # SYNOPSIS
7
7
  # viiite #{command_name} COMMAND
8
8
  #
9
9
  class Help < Quickl::Command(__FILE__, __LINE__)
10
-
10
+
11
11
  # Let NoSuchCommandError be passed to higher stage
12
12
  no_react_to Quickl::NoSuchCommand
13
-
13
+
14
14
  # Command execution
15
15
  def execute(args)
16
16
  sup = Quickl.super_command(self)
17
17
  sub = (args.size != 1) ? sup : Quickl.sub_command!(sup, args.first)
18
18
  puts Quickl.help(sub)
19
19
  end
20
-
20
+
21
21
  end # class Help
22
22
  end # class Command
23
23
  end # module Viiite
24
-
@@ -1,6 +1,6 @@
1
1
  module Viiite
2
2
  class Command < Quickl::Delegator(__FILE__, __LINE__)
3
- #
3
+ #
4
4
  # Report benchmarking results as a plot
5
5
  #
6
6
  # SYNOPSIS
@@ -10,35 +10,27 @@ module Viiite
10
10
  # #{summarized_options}
11
11
  #
12
12
  class Plot < Quickl::Command(__FILE__, __LINE__)
13
-
13
+ include Commons
14
+
14
15
  # Install options
15
16
  options do |opt|
16
17
  @render = :text
17
- opt.on('--text', "Render output as a text table") do
18
- @render = :text
19
- end
20
18
 
21
- opt.on("--gnuplot=[TERM]",
22
- "Render output as a gnuplot text (and terminal)") do |value|
23
- @render = :gnuplot
24
- @term = (value || "dumb").to_sym
19
+ @serie_style = nil
20
+ opt.on('--serie-style=FILE', "Specify a style file to use for series") do |value|
21
+ @serie_style = load_style(value)
25
22
  end
26
-
27
- @serie_style = File.expand_path("../serie_style.rash", __FILE__)
28
- opt.on('--style=FILE', "Specify a style file to use for series") do |value|
29
- @serie_style = value
30
- end
31
-
32
- @graph_style = File.expand_path("../graph_style.rash", __FILE__)
33
- opt.on('--style=FILE', "Specify a style file to use for graphs") do |value|
34
- @graph_style = value
23
+
24
+ @graph_style = nil
25
+ opt.on('--graph-style=FILE', "Specify a style file to use for graphs") do |value|
26
+ @graph_style = load_style(value)
35
27
  end
36
-
28
+
37
29
  @abscissa = :size
38
30
  opt.on('-x abscissa', "Specify the abscissa attribute") do |value|
39
31
  @abscissa = value.to_sym
40
32
  end
41
-
33
+
42
34
  @ordinate = "tms.total"
43
35
  opt.on('-y ordinate', "Specify the ordinate attribute") do |value|
44
36
  @ordinate = value
@@ -51,38 +43,46 @@ module Viiite
51
43
  end
52
44
 
53
45
  @graph = :ruby
54
- opt.on('--graph=ATTR',
46
+ opt.on('--graph=ATTR',
55
47
  "Specify the attribute to split graphs") do |value|
56
48
  @graph = value.to_sym
57
49
  end
50
+
51
+ @debug = false
52
+ opt.on('-d',
53
+ 'Print the query result instead of rendering') do
54
+ @debug = true
55
+ end
58
56
  end
59
-
60
- def query(op)
61
- lispy = Alf.lispy
62
- op = lispy.summarize(op, [@graph, @series, @abscissa].compact,
63
- {:y => "avg{ #{@ordinate} }"})
64
- op = lispy.join(op, Alf::Reader.reader(@serie_style))
65
- op = lispy.rename(op, @graph => :graph, @abscissa => :x, @series => :serie)
66
- op = lispy.group(op, [:x, :y], :data)
67
- op = lispy.rename(op, :serie => :title)
68
- op = lispy.group(op, [:graph], :series, {:allbut => true})
69
- op = lispy.join(op, Alf::Reader.reader(@graph_style))
70
- op = lispy.rename(op, :graph => :title)
71
- op
57
+
58
+ def load_style(file, reference = nil)
59
+ if reference
60
+ file = File.join("..", file)
61
+ file = File.expand_path(file, reference)
62
+ end
63
+ if File.extname(file) == ".rb"
64
+ Kernel.eval(File.read(file))
65
+ else
66
+ Alf::Reader.reader(file).to_rel
67
+ end
72
68
  end
73
-
74
- def execute(args)
75
- raise Quickl::InvalidArgument if args.size > 1
76
- op = query Alf::Reader.reader(args.first || $stdin)
77
- case @render
78
- when :text
69
+
70
+ def execute(argv)
71
+ lispy = Alf.lispy
72
+ op = single_source(argv) do |bdb, arg|
73
+ bdb.dataset(arg)
74
+ end
75
+ op = send(:"to_#{@render}_query", lispy, op)
76
+ if @debug
79
77
  Alf::Renderer.text(op).execute($stdout)
80
- when :gnuplot
81
- $stdout << "set terminal #{@term}\n"
82
- Viiite::Formatter::Plot::to_plots(op.to_a, $stdout)
78
+ else
79
+ send(:"to_#{@render}", lispy, op)
83
80
  end
84
81
  end
85
-
82
+
86
83
  end # class Plot
87
84
  end # class Command
88
85
  end # module Viiite
86
+ require 'viiite/command/plot/to_text'
87
+ require 'viiite/command/plot/to_gnuplot'
88
+ require 'viiite/command/plot/to_highcharts'