viiite 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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'