benchmark-memory 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,6 @@
1
- require "benchmark/memory/helpers"
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/memory/helpers'
2
4
 
3
5
  module Benchmark
4
6
  module Memory
@@ -22,10 +24,26 @@ module Benchmark
22
24
  #
23
25
  # @return [String]
24
26
  def to_s
25
- [
26
- format("%s %s", scale(metric.allocated), metric.type),
27
- format("(%s retained)", scale(metric.retained)),
28
- ].join(" ")
27
+ [allocated_message, retained_message].join(' ')
28
+ end
29
+
30
+ private
31
+
32
+ # @return [String] the formated string for allocated memory
33
+ def allocated_message
34
+ format(
35
+ '%<allocated>s %<type>s',
36
+ allocated: scale(metric.allocated),
37
+ type: metric.type
38
+ )
39
+ end
40
+
41
+ # @return [String] the formated string for retained memory
42
+ def retained_message
43
+ format(
44
+ '(%<retained>s retained)',
45
+ retained: scale(metric.retained)
46
+ )
29
47
  end
30
48
  end
31
49
  end
@@ -1,5 +1,7 @@
1
- require "benchmark/memory/job/io_output/comparison_formatter"
2
- require "benchmark/memory/job/io_output/entry_formatter"
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/memory/job/io_output/comparison_formatter'
4
+ require 'benchmark/memory/job/io_output/entry_formatter'
3
5
 
4
6
  module Benchmark
5
7
  module Memory
@@ -25,7 +27,7 @@ module Benchmark
25
27
  # @return [void]
26
28
  def put_comparison(comparison)
27
29
  @io.puts
28
- @io.puts "Comparison:"
30
+ @io.puts 'Comparison:'
29
31
  @io.puts ComparisonFormatter.new(comparison)
30
32
  end
31
33
 
@@ -33,7 +35,7 @@ module Benchmark
33
35
  #
34
36
  # @return [void]
35
37
  def put_header
36
- @io.puts "Calculating -------------------------------------"
38
+ @io.puts 'Calculating -------------------------------------'
37
39
  end
38
40
 
39
41
  # Put a notice that the execution is holding for another run.
@@ -41,8 +43,8 @@ module Benchmark
41
43
  # @return [void]
42
44
  def put_hold_notice
43
45
  @io.puts
44
- @io.puts "Pausing here -- run Ruby again to " \
45
- "measure the next benchmark..."
46
+ @io.puts 'Pausing here -- run Ruby again to ' \
47
+ 'measure the next benchmark...'
46
48
  end
47
49
  end
48
50
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Benchmark
2
4
  module Memory
3
5
  class Job
@@ -6,20 +8,17 @@ module Benchmark
6
8
  # Swallow entry output.
7
9
  #
8
10
  # @return [void]
9
- def put_entry(entry)
10
- end
11
+ def put_entry(entry); end
11
12
 
12
13
  # Swallow comparison output.
13
14
  #
14
15
  # @return [void]
15
- def put_comparison(comparison)
16
- end
16
+ def put_comparison(comparison); end
17
17
 
18
18
  # Swallow header output.
19
19
  #
20
20
  # @return [void]
21
- def put_header
22
- end
21
+ def put_header; end
23
22
  end
24
23
  end
25
24
  end
@@ -1,5 +1,7 @@
1
- require "memory_profiler"
2
- require "benchmark/memory/measurement"
1
+ # frozen_string_literal: true
2
+
3
+ require 'memory_profiler'
4
+ require 'benchmark/memory/measurement'
3
5
 
4
6
  module Benchmark
5
7
  module Memory
@@ -14,7 +16,7 @@ module Benchmark
14
16
  # @raise [ArgumentError] if the action does not respond to `#call`.
15
17
  def initialize(label, action)
16
18
  unless action.respond_to?(:call)
17
- fail(
19
+ raise(
18
20
  ArgumentError,
19
21
  "Invalid action (#{@action.inspect} does not respond to call)"
20
22
  )
@@ -1,9 +1,12 @@
1
- require "forwardable"
2
- require "benchmark/memory/job/task"
3
- require "benchmark/memory/job/io_output"
4
- require "benchmark/memory/job/null_output"
5
- require "benchmark/memory/held_results"
6
- require "benchmark/memory/report"
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'benchmark/memory/job/task'
5
+ require 'benchmark/memory/job/io_output'
6
+ require 'benchmark/memory/job/null_output'
7
+ require 'benchmark/memory/held_results'
8
+ require 'benchmark/memory/report'
9
+ require 'benchmark/memory/report/comparator'
7
10
 
8
11
  module Benchmark
9
12
  module Memory
@@ -18,7 +21,6 @@ module Benchmark
18
21
  #
19
22
  # @return [Job]
20
23
  def initialize(output: $stdout, quiet: false)
21
- @compare = false
22
24
  @full_report = Report.new
23
25
  @held_results = HeldResults.new
24
26
  @quiet = quiet
@@ -38,14 +40,14 @@ module Benchmark
38
40
  #
39
41
  # @return [Boolean]
40
42
  def compare?
41
- @compare
43
+ !!@comparator
42
44
  end
43
45
 
44
46
  # Enable output of a comparison of the different tasks.
45
47
  #
46
48
  # @return [void]
47
- def compare!
48
- @compare = true
49
+ def compare!(**spec)
50
+ @comparator = full_report.comparator = Report::Comparator.from_spec(spec.to_h)
49
51
  end
50
52
 
51
53
  # Enable holding results to compare between separate runs.
@@ -63,10 +65,8 @@ module Benchmark
63
65
  # @param block [Proc] Code the measure.
64
66
  #
65
67
  # @raise [ArgumentError] if no code block is specified.
66
- def report(label = "", &block)
67
- unless block_given?
68
- fail ArgumentError, "You did not specify a block for the item"
69
- end
68
+ def report(label = '', &block)
69
+ raise ArgumentError, 'You did not specify a block for the item' unless block_given?
70
70
 
71
71
  tasks.push Task.new(label, block)
72
72
  end
@@ -97,21 +97,9 @@ module Benchmark
97
97
  # @return [Boolean] A flag indicating whether to hold or not.
98
98
  def run_task(task)
99
99
  if @held_results.include?(task)
100
- measurement = @held_results[task.label]
101
- full_report.add_entry(task, measurement)
102
- return false
100
+ run_with_held_results(task)
103
101
  else
104
- measurement = task.call
105
- entry = full_report.add_entry(task, measurement)
106
- @output.put_entry(entry)
107
-
108
- if task == tasks.last
109
- @held_results.cleanup
110
- false
111
- else
112
- @held_results.add_result(entry)
113
- @held_results.holding?
114
- end
102
+ run_without_held_results(task)
115
103
  end
116
104
  end
117
105
 
@@ -119,9 +107,9 @@ module Benchmark
119
107
  #
120
108
  # @return [void]
121
109
  def run_comparison
122
- if compare? && full_report.comparable?
123
- @output.put_comparison(full_report.comparison)
124
- end
110
+ return unless compare? && full_report.comparable?
111
+
112
+ @output.put_comparison(full_report.comparison)
125
113
  end
126
114
 
127
115
  # Check whether the job is set to quiet.
@@ -130,6 +118,28 @@ module Benchmark
130
118
  def quiet?
131
119
  @quiet
132
120
  end
121
+
122
+ private
123
+
124
+ def run_with_held_results(task)
125
+ measurement = @held_results[task.label]
126
+ full_report.add_entry(task, measurement)
127
+ false
128
+ end
129
+
130
+ def run_without_held_results(task)
131
+ measurement = task.call
132
+ entry = full_report.add_entry(task, measurement)
133
+ @output.put_entry(entry)
134
+
135
+ if task == tasks.last
136
+ @held_results.cleanup
137
+ false
138
+ else
139
+ @held_results.add_result(entry)
140
+ @held_results.holding?
141
+ end
142
+ end
133
143
  end
134
144
  end
135
145
  end
@@ -1,12 +1,12 @@
1
- require "benchmark/memory/helpers"
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/memory/helpers'
2
4
 
3
5
  module Benchmark
4
6
  module Memory
5
7
  class Measurement
6
8
  # Describe the ratio of allocated vs. retained memory in a measurement.
7
9
  class Metric
8
- include Comparable
9
-
10
10
  # Instantiate a Metric of allocated vs. retained memory.
11
11
  #
12
12
  # @param type [Symbol] The type of memory allocated in the metric.
@@ -26,15 +26,6 @@ module Benchmark
26
26
 
27
27
  # @return [Symbol] The type of memory allocated in the metric.
28
28
  attr_reader :type
29
-
30
- # Sort by the total allocated.
31
- #
32
- # @param other [Metric] The other metric.
33
- #
34
- # @return [Integer]
35
- def <=>(other)
36
- allocated <=> other.allocated
37
- end
38
29
  end
39
30
  end
40
31
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/memory/measurement/metric'
4
+
5
+ module Benchmark
6
+ module Memory
7
+ # Extracts metrics from a memory profiler result
8
+ class MetricExtractor
9
+ # Extracts the memory-specific metrics from a profiler result
10
+ #
11
+ # @param result [MemoryProfiler::Results]
12
+ # @return [Benchmark::Memory::Measurement::Metric]
13
+ def self.extract_memory(result)
14
+ Measurement::Metric.new(
15
+ :memsize,
16
+ result.total_allocated_memsize,
17
+ result.total_retained_memsize
18
+ )
19
+ end
20
+
21
+ # Extracts the object-specific metrics from a profiler result
22
+ #
23
+ # @param result [MemoryProfiler::Results]
24
+ # @return [Benchmark::Memory::Measurement::Metric]
25
+ def self.extract_objects(result)
26
+ Measurement::Metric.new(
27
+ :objects,
28
+ result.total_allocated,
29
+ result.total_retained
30
+ )
31
+ end
32
+
33
+ # Extracts the string-specific metrics from a profiler result
34
+ #
35
+ # @param result [MemoryProfiler::Results]
36
+ # @return [Benchmark::Memory::Measurement::Metric]
37
+ def self.extract_strings(result)
38
+ Measurement::Metric.new(
39
+ :strings,
40
+ result.strings_allocated.size,
41
+ result.strings_retained.size
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,11 +1,12 @@
1
- require "forwardable"
2
- require "benchmark/memory/measurement/metric"
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'benchmark/memory/measurement/metric_extractor'
3
5
 
4
6
  module Benchmark
5
7
  module Memory
6
8
  # Encapsulate the combined metrics of an action.
7
9
  class Measurement
8
- include Comparable
9
10
  include Enumerable
10
11
  extend Forwardable
11
12
 
@@ -14,23 +15,11 @@ module Benchmark
14
15
  # @param result [MemoryProfiler::Results]
15
16
  # The results of a MemoryProfiler report.
16
17
  def self.from_result(result)
17
- memory = Metric.new(
18
- :memsize,
19
- result.total_allocated_memsize,
20
- result.total_retained_memsize
21
- )
22
- objects = Metric.new(
23
- :objects,
24
- result.total_allocated,
25
- result.total_retained
26
- )
27
- strings = Metric.new(
28
- :strings,
29
- result.strings_allocated.size,
30
- result.strings_retained.size
31
- )
18
+ memory = MetricExtractor.extract_memory(result)
19
+ objects = MetricExtractor.extract_objects(result)
20
+ strings = MetricExtractor.extract_strings(result)
32
21
 
33
- new(:memory => memory, :objects => objects, :strings => strings)
22
+ new(memory: memory, objects: objects, strings: strings)
34
23
  end
35
24
 
36
25
  # Instantiate a Measurement of memory usage.
@@ -59,22 +48,6 @@ module Benchmark
59
48
 
60
49
  # Enumerate through the metrics when enumerating a measurement.
61
50
  def_delegator :metrics, :each
62
-
63
- # Compare two measurements for sorting purposes.
64
- #
65
- # @param other [Measurement] The other measurement
66
- #
67
- # @return [Integer]
68
- def <=>(other)
69
- memory <=> other.memory
70
- end
71
-
72
- # Total amount of allocated memory for the measurement.
73
- #
74
- # @return [Integer]
75
- def allocated_memory
76
- memory.allocated
77
- end
78
51
  end
79
52
  end
80
53
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Benchmark
4
+ module Memory
5
+ class Report
6
+ # Compares two {Entry} for the purposes of sorting and outputting a {Comparison}.
7
+ class Comparator
8
+ # @private
9
+ METRICS = %i[memory objects strings].freeze
10
+
11
+ # @private
12
+ VALUES = %i[allocated retained].freeze
13
+
14
+ # Instantiates a {Comparator} from a spec given by {Job#compare!}
15
+ #
16
+ # @param spec [Hash<Symbol, Symbol>] The specification given for the {Comparator}
17
+ # @return [Comparator]
18
+ def self.from_spec(spec)
19
+ raise ArgumentError, 'Only send a single metric and value, in the form memory: :allocated' if spec.length > 1
20
+
21
+ metric, value = *spec.first
22
+ metric ||= :memory
23
+ value ||= :allocated
24
+
25
+ new(metric: metric, value: value)
26
+ end
27
+
28
+ # Instantiate a new comparator
29
+ #
30
+ # @param metric [Symbol] (see #metric)
31
+ # @param value [Symbol] (see #value)
32
+ def initialize(metric: :memory, value: :allocated)
33
+ raise ArgumentError, "Invalid metric: #{metric.inspect}" unless METRICS.include? metric
34
+ raise ArgumentError, "Invalid value: #{value.inspect}" unless VALUES.include? value
35
+
36
+ @metric = metric
37
+ @value = value
38
+ end
39
+
40
+ # @return [Symbol] The metric to compare, one of `:memory`, `:objects`, or `:strings`
41
+ attr_reader :metric
42
+
43
+ # @return [Symbol] The value to compare, one of `:allocated` or `:retained`
44
+ attr_reader :value
45
+
46
+ # Checks whether a {Comparator} equals another
47
+ #
48
+ # @param other [Benchmark::Memory::Comparator] The comparator to check against
49
+ #
50
+ # @return [Boolean]
51
+ def ==(other)
52
+ metric == other.metric && value == other.value
53
+ end
54
+
55
+ # Converts the {Comparator} to a Proc for passing to a block
56
+ #
57
+ # @return [Proc]
58
+ def to_proc
59
+ proc { |entry| entry.measurement.public_send(metric).public_send(value) }
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,18 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Benchmark
2
4
  module Memory
3
5
  class Report
4
6
  # Compare entries against each other.
5
7
  class Comparison
8
+ extend Forwardable
9
+
6
10
  # Instantiate a new comparison.
7
11
  #
8
12
  # @param entries [Array<Entry>] The entries to compare.
9
- def initialize(entries)
10
- @entries = entries.sort_by(&:measurement)
13
+ # @param comparator [Comparator] The comparator to use when generating.
14
+ def initialize(entries, comparator)
15
+ @entries = entries.sort_by(&comparator)
16
+ @comparator = comparator
11
17
  end
12
18
 
19
+ # @return [Comparator] The {Comparator} to use when generating the {Comparison}.
20
+ attr_reader :comparator
21
+
13
22
  # @return [Array<Entry>] The entries to compare.
14
23
  attr_reader :entries
15
24
 
25
+ # @!method metric
26
+ # @return [Symbol] The metric to compare, one of `:memory`, `:objects`, or `:strings`
27
+ # @!method value
28
+ # @return [Symbol] The value to compare, one of `:allocated` or `:retained`
29
+ def_delegators :@comparator, :metric, :value
30
+
16
31
  # Check if the comparison is possible
17
32
  #
18
33
  # @return [Boolean]
@@ -1,4 +1,6 @@
1
- require "forwardable"
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
2
4
 
3
5
  module Benchmark
4
6
  module Memory
@@ -22,9 +24,10 @@ module Benchmark
22
24
 
23
25
  # Get the total amount of memory allocated in the entry.
24
26
  #
27
+ # @param comparison [Comparison] The {Comparison} to compare.
25
28
  # @return [Integer]
26
- def allocated_memory
27
- measurement.memory.allocated
29
+ def compared_metric(comparison)
30
+ measurement.public_send(comparison.metric).public_send(comparison.value)
28
31
  end
29
32
  end
30
33
  end
@@ -1,5 +1,7 @@
1
- require "benchmark/memory/report/comparison"
2
- require "benchmark/memory/report/entry"
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/memory/report/comparison'
4
+ require 'benchmark/memory/report/entry'
3
5
 
4
6
  module Benchmark
5
7
  module Memory
@@ -10,8 +12,12 @@ module Benchmark
10
12
  # @return [Report]
11
13
  def initialize
12
14
  @entries = []
15
+ @comparator = Comparator.new
13
16
  end
14
17
 
18
+ # @return [Comparator] The {Comparator} to use when creating the {Comparison}.
19
+ attr_accessor :comparator
20
+
15
21
  # @return [Array<Entry>] The entries in the report.
16
22
  attr_reader :entries
17
23
 
@@ -38,7 +44,7 @@ module Benchmark
38
44
  #
39
45
  # @return [Comparison]
40
46
  def comparison
41
- @comparison ||= Comparison.new(entries)
47
+ @comparison ||= Comparison.new(entries, comparator)
42
48
  end
43
49
  end
44
50
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Benchmark
2
4
  module Memory
3
- VERSION = "0.1.2".freeze
5
+ VERSION = '0.2.0'
4
6
  end
5
7
  end
@@ -1,6 +1,8 @@
1
- require "benchmark/memory/errors"
2
- require "benchmark/memory/job"
3
- require "benchmark/memory/version"
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/memory/errors'
4
+ require 'benchmark/memory/job'
5
+ require 'benchmark/memory/version'
4
6
 
5
7
  # Performance benchmarking library
6
8
  module Benchmark
@@ -13,14 +15,9 @@ module Benchmark
13
15
  #
14
16
  # @return [Report]
15
17
  def memory(quiet: false)
16
- unless block_given?
17
- fail(
18
- ConfigurationError,
19
- "You did not give a test block to your call to `Benchmark.memory`"
20
- )
21
- end
18
+ raise ConfigurationError unless block_given?
22
19
 
23
- job = Job.new(:quiet => quiet)
20
+ job = Job.new(quiet: quiet)
24
21
 
25
22
  yield job
26
23
 
@@ -1,2 +1,3 @@
1
- # rubocop:disable Style/FileName
2
- require "benchmark/memory"
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/memory'