micro_bench 0.1.3 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5eeb98130357a3e9320237286d468300c1731a76
4
- data.tar.gz: 1a5a9887fc7c0b9600c453565cb3496db58e2de5
2
+ SHA256:
3
+ metadata.gz: e7b61de43614716fc3e48d6661bc4f77524092a7766cd808a5cfdb09e4a70f3b
4
+ data.tar.gz: 25deba16810136e20ba13a28dde5b73a63b57a7e639700582b726f9853f8fe9c
5
5
  SHA512:
6
- metadata.gz: 958052ea9ea084cc0bcba112f41e6de68d9395d5d4e711c0ccc394ad4c82e628463bbd18cd0c1b231c5f906e42c682b7d191aa59a698283d0316d95b549e39fe
7
- data.tar.gz: 6dc33d748019010708d9676bc793717a4e54289e11eb74344478384d48b638077164e6a97a41230a1119f5545a492fb3c2e7fd984bab51d08dafac2f44f4c090
6
+ metadata.gz: 9cdb819b4a60cdc8a7eb958a222217942ff90da5896698af0f2c66b66ed8ccc62f5583241962c0479181aadcf5a098d66505d6a3172dde7246e239d6fffb66f3
7
+ data.tar.gz: 6612a374748347f8858cacf36acfa0b712c0d8c93a86242896203558261eb748d49c303aff25602ec89a0f34f08e2c34a67b8a92955e20e59027bb4fac70e363
data/README.md CHANGED
@@ -2,10 +2,17 @@
2
2
  # MicroBench
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/micro_bench.svg)](https://badge.fury.io/rb/micro_bench)
5
+ [![CircleCI](https://circleci.com/gh/klaxit/micro_bench.svg?style=shield)](https://circleci.com/gh/klaxit/micro_bench)
6
+
7
+ ```
8
+ gem install micro_bench
9
+ ```
10
+
11
+ ## Why ?
5
12
 
6
13
  Ruby `Benchmark` module is nice but it uses blocks. We see 2 problems to it :
7
14
  - if we want to instrument a snippet of code, it breaks git history,
8
- - variables are tied to the benchmark block, so we have to initialize them outside of the benchmark block to use them subsequently.
15
+ - variables declared in the benchmark block cannot be used subsequently.
9
16
 
10
17
  Let's say you want to output the duration of `method_1` from :
11
18
 
@@ -32,7 +39,10 @@ puts "Method 1 duration : #{MicroBench.duration} seconds"
32
39
  method_2(foo)
33
40
  ```
34
41
 
35
- **WARNING : This is still beta code and may not be suitable for production usage. While still in beta, API may be subject to breaking changes on MINOR versions (but not on PATCH versions).**
42
+ ## Project maturity
43
+
44
+ This has been running in production at [Klaxit](https://www.klaxit.com) for some months now, but it is still a young library. API may be subject to breaking changes on MINOR versions (but not on PATCH versions).
45
+
36
46
 
37
47
  ## Install
38
48
 
@@ -114,6 +124,31 @@ end
114
124
  method_1
115
125
  ```
116
126
 
127
+ ### Configuration
128
+
129
+ You can configure a bit `MicroBench` to have an even simpler time using it afterwards. Here's how:
130
+
131
+ ```ruby
132
+ MicroBench.configure do |config|
133
+ config.formatter = ->(duration) { "#{duration.round} seconds" }
134
+ end
135
+
136
+ MicroBench.start
137
+ sleep 2
138
+ MicroBench.duration == "2 seconds"
139
+ ```
140
+
141
+ There are some default formatters that you can set:
142
+
143
+ | id | result | description |
144
+ | --------- | ---------------------------- | ---------------------------------------- |
145
+ | `default` | `722.327823832` | the raw original float, for computation |
146
+ | `simple` | `722.33` | rounds to 2 digits |
147
+ | `mmss` | `"12:02.328"` | Easy to understand, lossless and compact |
148
+ | `human` | `"12 minutes and 2 seconds"` | For humans, clutters logs |
149
+
150
+ To use one of those, simply write `config.formatter = :simple` instead of a lambda.
151
+
117
152
  ## Versioning
118
153
 
119
154
  We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/klaxit/micro_bench/tags).
@@ -1,5 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MicroBench
2
4
  class << self
5
+ # Configure MicroBench.
6
+ #
7
+ # == Example usage:
8
+ # MicroBench.configure do |config|
9
+ # config.formatter = proc { |duration| duration.ceil }
10
+ # end
11
+ def configure(&block)
12
+ block.call(configurations)
13
+ nil
14
+ end
15
+
3
16
  # Start a benchmark
4
17
  #
5
18
  # == Parameters:
@@ -52,11 +65,17 @@ module MicroBench
52
65
  # MicroBench.stop(:my_benchmark)
53
66
  #
54
67
  def duration(bench_id = nil)
55
- benchmarks[benchmark_key(bench_id)]&.duration
68
+ configurations.formatter.call(
69
+ benchmarks[benchmark_key(bench_id)]&.duration
70
+ )
56
71
  end
57
72
 
58
73
  private
59
74
 
75
+ def configurations
76
+ @configurations ||= Configurations.new
77
+ end
78
+
60
79
  def benchmarks
61
80
  @benchmarks ||= {}
62
81
  end
@@ -79,3 +98,4 @@ module MicroBench
79
98
  end
80
99
 
81
100
  require "micro_bench/benchmark"
101
+ require "micro_bench/configurations"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class MicroBench::Benchmark
2
4
  def initialize
3
5
  @start_time = monotonic_clock_time
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MicroBench::Configurations
4
+ attr_reader :formatter
5
+
6
+ # Initialize with a default formatters that changes nothing.
7
+ def initialize
8
+ @formatter = method(:default_formatter)
9
+ end
10
+
11
+ # Set formatter to change {MicroBench.duration} results.
12
+ #
13
+ # == Parameters:
14
+ # value::
15
+ # It can be a proc that receives a duration float in seconds and returns any
16
+ # formatted value. Or it can be one of the default values, +"simple"+,
17
+ # +"mmss"+ or +"human"+. If you set it to +nil+ or +"default"+, the
18
+ # formatter will be ignored, and the result will be the raw float.
19
+ def formatter=(value)
20
+ # This ensures that both Proc and Method can be used there. Or even a user
21
+ # defined class that responds to call.
22
+ if value.respond_to?(:call)
23
+ @formatter = value
24
+ return
25
+ end
26
+
27
+ formatter_method =
28
+ case value.to_s
29
+ when "", "default"
30
+ :default_formatter
31
+ when "simple"
32
+ :simple_formatter
33
+ when "mmss"
34
+ :mmss_formatter
35
+ when "human"
36
+ :human_formatter
37
+ else
38
+ raise ArgumentError, "formatter must be callable or a default string"
39
+ end
40
+
41
+ @formatter = method(formatter_method)
42
+ end
43
+
44
+ private
45
+
46
+ def default_formatter(duration)
47
+ duration
48
+ end
49
+
50
+ def simple_formatter(duration)
51
+ duration.round(2)
52
+ end
53
+
54
+ def mmss_formatter(duration)
55
+ ss, ms = duration.divmod(1)
56
+ mm, ss = ss.divmod(60)
57
+ hh, mm = mm.divmod(60)
58
+
59
+ # Format ms to have only 3 digits.
60
+ ms = (ms * 1_000).round
61
+
62
+ return format("%02d:%02d:%02d.%03d", hh, mm, ss, ms) if hh > 0
63
+ return format("%02d:%02d.%03d", mm, ss, ms) if mm > 0
64
+ return format("%d.%03d", ss, ms)
65
+ end
66
+
67
+ def human_formatter(duration)
68
+ ss = duration.round
69
+ mm, ss = ss.divmod(60)
70
+ hh, mm = mm.divmod(60)
71
+
72
+ human_unit = ->(value, name) { "#{value} #{name}#{"s" unless value == 1}" }
73
+
74
+ hours = human_unit[hh, "hour"]
75
+ minutes = human_unit[mm, "minute"]
76
+ seconds = human_unit[ss, "second"]
77
+
78
+ human_join = ->(*array) { array[0..-2].join(", ") + " and #{array.last}" }
79
+
80
+ return human_join[hours, minutes, seconds] if hh > 0
81
+ return human_join[minutes, seconds] if mm > 0
82
+ return seconds
83
+ end
84
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MicroBench
2
- VERSION = "0.1.3".freeze
4
+ VERSION = "0.2.3"
3
5
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe MicroBench::Configurations do
4
+ let(:duration) { rand(10) + rand }
5
+
6
+ describe "#default_formatter" do
7
+ it "does nothing" do
8
+ expect(subject.send(:default_formatter, duration)).to eq duration
9
+ end
10
+ end
11
+
12
+ describe "#simple_formatter" do
13
+ it "rounds" do
14
+ expect(subject.send(:simple_formatter, duration)).to eq duration.round(2)
15
+ end
16
+ end
17
+
18
+ describe "#mmss_formatter" do
19
+ it "gives hh:mm:ss.s" do
20
+ expect(subject.send(:mmss_formatter, 457927.127)).to eq "127:12:07.127"
21
+ end
22
+ end
23
+
24
+ describe "#human_formatter" do
25
+ it "gives a text" do
26
+ expect(subject.send(:human_formatter, 457287.4699882))
27
+ .to eq "127 hours, 1 minute and 27 seconds"
28
+ end
29
+ end
30
+ end
@@ -1,4 +1,4 @@
1
- require "spec_helper"
1
+ # frozen_string_literal: true
2
2
 
3
3
  describe MicroBench do
4
4
  it "gives seconds duration doing something" do
@@ -91,10 +91,10 @@ describe MicroBench do
91
91
  end
92
92
 
93
93
  it "allows referencing a benchmark from a Proc / Block / Lambda" do
94
- MicroBench.start
94
+ described_class.start
95
95
  # from a Proc
96
96
  proc = Proc.new do
97
- expect(MicroBench.duration).to_not be_nil
97
+ expect(described_class.duration).to_not be_nil
98
98
  end
99
99
  proc.call
100
100
  # from a Block
@@ -102,12 +102,28 @@ describe MicroBench do
102
102
  yield
103
103
  end
104
104
  my_method do
105
- expect(MicroBench.duration).to_not be_nil
105
+ expect(described_class.duration).to_not be_nil
106
106
  end
107
107
  # from a Lambda
108
108
  l = lambda do
109
- expect(MicroBench.duration).to_not be_nil
109
+ expect(described_class.duration).to_not be_nil
110
110
  end
111
111
  l.call
112
112
  end
113
+
114
+ it "formats duration when configured with an id" do
115
+ described_class.configure do |config|
116
+ config.formatter = :human
117
+ end
118
+ described_class.start
119
+ expect(described_class.duration).to eq "0 seconds"
120
+ end
121
+
122
+ it "formats duration when using a callable" do
123
+ described_class.configure do |config|
124
+ config.formatter = proc { "result" }
125
+ end
126
+ described_class.start
127
+ expect(described_class.duration).to eq "result"
128
+ end
113
129
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: micro_bench
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyrille Courtière
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-04 00:00:00.000000000 Z
11
+ date: 2020-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.8'
41
- description:
41
+ description:
42
42
  email:
43
43
  - cyrille@klaxit.com
44
44
  executables: []
@@ -48,14 +48,16 @@ files:
48
48
  - README.md
49
49
  - lib/micro_bench.rb
50
50
  - lib/micro_bench/benchmark.rb
51
+ - lib/micro_bench/configurations.rb
51
52
  - lib/micro_bench/version.rb
52
- - spec/micro_bench/micro_bench_spec.rb
53
+ - spec/micro_bench/configurations_spec.rb
54
+ - spec/micro_bench_spec.rb
53
55
  - spec/spec_helper.rb
54
56
  homepage: http://github.com/klaxit/micro_bench
55
57
  licenses:
56
58
  - MIT
57
59
  metadata: {}
58
- post_install_message:
60
+ post_install_message:
59
61
  rdoc_options: []
60
62
  require_paths:
61
63
  - lib
@@ -70,11 +72,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
72
  - !ruby/object:Gem::Version
71
73
  version: '0'
72
74
  requirements: []
73
- rubyforge_project:
74
- rubygems_version: 2.5.2.3
75
- signing_key:
75
+ rubygems_version: 3.1.0.pre3
76
+ signing_key:
76
77
  specification_version: 4
77
78
  summary: Dead simple benchmarks
78
79
  test_files:
79
- - spec/micro_bench/micro_bench_spec.rb
80
+ - spec/micro_bench/configurations_spec.rb
81
+ - spec/micro_bench_spec.rb
80
82
  - spec/spec_helper.rb