Class: Bullshit::Case
- Inherits:
-
Object
- Object
- Bullshit::Case
- Extended by:
- DSLKit::DSLAccessor
- Defined in:
- lib/bullshit.rb
Overview
This is the base class of all Benchmarking Cases.
Direct Known Subclasses
Defined Under Namespace
Modules: CaseExtension
Instance Attribute Summary collapse
-
#clocks ⇒ Object
readonly
The clock instances, that were used during a run of this benchmark case.
Class Method Summary collapse
-
.autorun_all ⇒ Object
Autorun all subclasses’ instances, that is all Bullshit cases.
-
.each(&block) ⇒ Object
Iterate over all subclasses of class Case.
- .inherited(klass) ⇒ Object
- .output_filename(name) ⇒ Object
-
.run(do_compare = true) ⇒ Object
Creates an instance of this class and run it.
-
.run_all ⇒ Object
Run all subclasses’ instances, that is all Bullshit cases, unless they already have run.
-
.run_count ⇒ Object
Returns the total number of run counts
run_count
. -
.sorted_bmethods ⇒ Object
Return all benchmark methods of this Case instance lexicographically sorted.
Instance Method Summary collapse
-
#[](method_name) ⇒ Object
Return the CaseMethod instance for
method_name
or nil, if there isn’t any method of this name. -
#bmethods ⇒ Object
Return all benchmark methods of this Case instance in a random order.
-
#evaluation(clock) ⇒ Object
This method has to be implemented in subclasses, it should return the evaluation results of the benchmarks as a string.
-
#initialize ⇒ Case
constructor
Returns a Case instance, that is used to run benchmark methods and measure their running time.
-
#longest_name ⇒ Object
Return the length of the longest_name of all these methods’ names.
-
#post_run(bc_method) ⇒ Object
Output after
bc_method
is run. -
#pre_run(bc_method) ⇒ Object
Output before
bc_method
is run. -
#run(do_compare = true) ⇒ Object
Setup, run all benchmark cases (warmup and the real run) and output results, run method speed comparisons, and teardown.
-
#run_method(bc_method) ⇒ Object
Run only pre_run and post_run methods.
-
#run_once ⇒ Object
Run benchmark case once and output results.
-
#setup ⇒ Object
General setup for all the benchmark methods.
-
#teardown ⇒ Object
General teardown for all the benchmark methods.
-
#to_s ⇒ Object
Return the name of the benchmark case as a string.
-
#write_files ⇒ Object
Write all output files after run.
Constructor Details
#initialize ⇒ Case
Returns a Case instance, that is used to run benchmark methods and measure their running time.
707 708 709 710 711 712 713 |
# File 'lib/bullshit.rb', line 707 def initialize @clocks = [] if self.class.comparison @comparison = Comparison.new @comparison.output self.class.output end end |
Instance Attribute Details
#clocks ⇒ Object (readonly)
The clock instances, that were used during a run of this benchmark case.
830 831 832 |
# File 'lib/bullshit.rb', line 830 def clocks @clocks end |
Class Method Details
.autorun_all ⇒ Object
Autorun all subclasses’ instances, that is all Bullshit cases. If its autorun dsl_accessor is false or it has already run, don’t run the case.
698 699 700 701 702 |
# File 'lib/bullshit.rb', line 698 def autorun_all each do |bc_class| bc_class.autorun and bc_class.run_count == 0 and bc_class.run end end |
.each(&block) ⇒ Object
Iterate over all subclasses of class Case.
683 684 685 |
# File 'lib/bullshit.rb', line 683 def each(&block) cases.each(&block) end |
.inherited(klass) ⇒ Object
660 661 662 |
# File 'lib/bullshit.rb', line 660 def inherited(klass) klass.extend CaseExtension end |
.output_filename(name) ⇒ Object
670 671 672 673 |
# File 'lib/bullshit.rb', line 670 def output_filename(name) path = File.(name, output_dir) output File.new(path, 'a+') end |
.run(do_compare = true) ⇒ Object
Creates an instance of this class and run it.
851 852 853 |
# File 'lib/bullshit.rb', line 851 def self.run(do_compare = true) new.run do_compare end |
.run_all ⇒ Object
Run all subclasses’ instances, that is all Bullshit cases, unless they already have run.
689 690 691 692 693 |
# File 'lib/bullshit.rb', line 689 def run_all each do |bc_class| bc_class.run_count == 0 and bc_class.run end end |
.run_count ⇒ Object
Returns the total number of run counts run_count
.
676 677 678 |
# File 'lib/bullshit.rb', line 676 def run_count cases.inject(0) { |s, c| s + c.run_count } end |
.sorted_bmethods ⇒ Object
Return all benchmark methods of this Case instance lexicographically sorted.
722 723 724 |
# File 'lib/bullshit.rb', line 722 def self.sorted_bmethods instance_methods.map { |x| x.to_s }.grep(/\Abenchmark_/).sort end |
Instance Method Details
#[](method_name) ⇒ Object
Return the CaseMethod instance for method_name
or nil, if there isn’t any method of this name.
739 740 741 742 |
# File 'lib/bullshit.rb', line 739 def [](method_name) method_name = "benchmark_#{method_name}" bmethods.find { |bm| bm.name == method_name } end |
#bmethods ⇒ Object
Return all benchmark methods of this Case instance in a random order.
727 728 729 730 731 732 733 734 735 |
# File 'lib/bullshit.rb', line 727 def bmethods unless @bmethods @bmethods = self.class.sorted_bmethods.sort_by do rand end @bmethods.map! { |n| CaseMethod.new(n, self) } end @bmethods end |
#evaluation(clock) ⇒ Object
This method has to be implemented in subclasses, it should return the evaluation results of the benchmarks as a string.
908 909 910 |
# File 'lib/bullshit.rb', line 908 def evaluation(clock) raise NotImplementedError, "has to be implemented in subclasses" end |
#longest_name ⇒ Object
Return the length of the longest_name of all these methods’ names.
745 746 747 748 |
# File 'lib/bullshit.rb', line 745 def longest_name bmethods.empty? and return 0 bmethods.map { |x| x.short_name.size }.max end |
#post_run(bc_method) ⇒ Object
Output after bc_method
is run.
913 914 915 916 917 918 919 |
# File 'lib/bullshit.rb', line 913 def post_run(bc_method) teardown_name = bc_method.teardown_name if respond_to? teardown_name $DEBUG and warn "Calling #{teardown_name}." __send__(bc_method.teardown_name) end end |
#pre_run(bc_method) ⇒ Object
Output before bc_method
is run.
885 886 887 888 889 890 891 892 |
# File 'lib/bullshit.rb', line 885 def pre_run(bc_method) setup_name = bc_method.setup_name if respond_to? setup_name $DEBUG and warn "Calling #{setup_name}." __send__(setup_name) end self.class.output.puts "#{bc_method.long_name}:" end |
#run(do_compare = true) ⇒ Object
Setup, run all benchmark cases (warmup and the real run) and output results, run method speed comparisons, and teardown.
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 |
# File 'lib/bullshit.rb', line 834 def run(do_compare = true) old_sync, self.class.output.sync = self.class.output.sync, true $DEBUG and warn "Calling setup." setup run_once do_compare and @comparison and @comparison.display self rescue => e warn "Caught #{e.class}: #{e}\n\n#{e.backtrace.map { |x| "\t#{x}\n" }}" ensure $DEBUG and warn "Calling teardown." teardown @clocks and write_files self.class.output.sync = old_sync end |
#run_method(bc_method) ⇒ Object
Run only pre_run and post_run methods. Yield to the block, if one was given.
896 897 898 899 900 901 902 903 904 |
# File 'lib/bullshit.rb', line 896 def run_method(bc_method) pre_run bc_method clock = self.class.clock.__send__(self.class.clock_method, bc_method) do __send__(bc_method.name) end bc_method.clock = clock post_run bc_method clock end |
#run_once ⇒ Object
Run benchmark case once and output results.
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 |
# File 'lib/bullshit.rb', line 751 def run_once self.class.run_count(self.class.run_count + 1) self.class.output.puts Time.now.strftime(' %FT%T %Z ').center(COLUMNS, '=') self.class.output.puts "Benchmarking on #{RUBY_DESCRIPTION}." self.class.output.puts self.class. self.class.output.puts '=' * COLUMNS, '' @clocks.clear if self.class.warmup == :aggressive self.class.output.puts "Aggressively run all benchmarks for warmup first.", '' bmethods.each do |bc_method| GC.start clock = run_method bc_method self.class.output.puts evaluation(clock) GC.start end self.class.output.puts "Aggressive warmup done.", '', '=' * COLUMNS, '' end first = true bmethods.each do |bc_method| if first first = false else self.class.output.puts '-' * COLUMNS, '' end if self.class.warmup self.class.output.puts "This first run is only for warmup." GC.start clock = run_method bc_method self.class.output.puts evaluation(clock) GC.start end clock = run_method(bc_method) if self.class.truncate_data.enabled = '' offset = clock.find_truncation_offset if clock.case.data_file slopes_file_path = clock.file_path 'slopes' << "Writing slopes data file '#{slopes_file_path}'.\n" File.open(slopes_file_path, 'w') do |slopes_file| slopes_file.puts %w[#scatter slope] * "\t" slopes_file.puts clock.slopes.map { |s| s * "\t" } end end case offset when 0 << "No initial data truncated.\n =>"\ " System may have been in a steady state from the beginning." when clock.repeat << "After truncating measurements no data would have"\ " remained.\n => No steady state could be detected." else if clock.case.data_file data_file_path = clock.file_path 'untruncated' << "Writing untruncated measurement data file '#{data_file_path}'.\n" File.open(data_file_path, 'w') do |data_file| data_file.puts clock.class.to_a * "\t" data_file.puts clock.to_a.map { |times| times * "\t" } end end remaining = clock.repeat - offset offset_percentage = 100 * offset.to_f / clock.repeat << sprintf("Truncated initial %u measurements: "\ "%u -> %u (-%0.2f%%).\n", offset, clock.repeat, remaining, offset_percentage) clock.truncate_data(offset) end self.class.output.puts evaluation(clock), else self.class.output.puts evaluation(clock) end @clocks << clock if @comparison @comparison.benchmark(self, bc_method.short_name, :run => false) end end @clocks end |
#setup ⇒ Object
General setup for all the benchmark methods.
922 923 |
# File 'lib/bullshit.rb', line 922 def setup end |
#teardown ⇒ Object
General teardown for all the benchmark methods.
926 927 |
# File 'lib/bullshit.rb', line 926 def teardown end |
#to_s ⇒ Object
Return the name of the benchmark case as a string.
716 717 718 |
# File 'lib/bullshit.rb', line 716 def to_s self.class.benchmark_name end |
#write_files ⇒ Object
Write all output files after run.
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 |
# File 'lib/bullshit.rb', line 856 def write_files for clock in @clocks if clock.case.data_file data_file_path = clock.file_path self.class.output.puts "Writing measurement data file '#{data_file_path}'." File.open(data_file_path, 'w') do |data_file| data_file.puts clock.class.to_a * "\t" data_file.puts clock.to_a.map { |times| times * "\t" } end end if clock.case.histogram.enabled and clock.case.histogram.file histogram_file_path = clock.file_path 'histogram' self.class.output.puts "Writing histogram file '#{histogram_file_path}'." File.open(histogram_file_path, 'w') do |data_file| data_file.puts %w[#binleft frequency binright] * "\t" data_file.puts clock.histogram(clock.case.compare_time).to_a.map { |times| times * "\t" } end end if clock.case.autocorrelation.enabled and clock.case.autocorrelation.file ac_plot_file_path = clock.file_path 'autocorrelation' self.class.output.puts "Writing autocorrelation plot file '#{ac_plot_file_path}'." File.open(ac_plot_file_path, 'w') do |data_file| data_file.puts %w[#lag autocorrelation] * "\t" data_file.puts clock.autocorrelation_plot(clock.case.compare_time).to_a.map { |ac| ac * "\t" } end end end end |