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 +5 -5
- data/README.md +37 -2
- data/lib/micro_bench.rb +21 -1
- data/lib/micro_bench/benchmark.rb +2 -0
- data/lib/micro_bench/configurations.rb +84 -0
- data/lib/micro_bench/version.rb +3 -1
- data/spec/micro_bench/configurations_spec.rb +30 -0
- data/spec/{micro_bench/micro_bench_spec.rb → micro_bench_spec.rb} +21 -5
- metadata +12 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e7b61de43614716fc3e48d6661bc4f77524092a7766cd808a5cfdb09e4a70f3b
|
4
|
+
data.tar.gz: 25deba16810136e20ba13a28dde5b73a63b57a7e639700582b726f9853f8fe9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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).
|
data/lib/micro_bench.rb
CHANGED
@@ -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
|
-
|
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"
|
@@ -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
|
data/lib/micro_bench/version.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
94
|
+
described_class.start
|
95
95
|
# from a Proc
|
96
96
|
proc = Proc.new do
|
97
|
-
expect(
|
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(
|
105
|
+
expect(described_class.duration).to_not be_nil
|
106
106
|
end
|
107
107
|
# from a Lambda
|
108
108
|
l = lambda do
|
109
|
-
expect(
|
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.
|
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:
|
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/
|
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
|
-
|
74
|
-
|
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/
|
80
|
+
- spec/micro_bench/configurations_spec.rb
|
81
|
+
- spec/micro_bench_spec.rb
|
80
82
|
- spec/spec_helper.rb
|