micro_bench 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +102 -0
- data/lib/micro_bench/benchmark.rb +31 -0
- data/lib/micro_bench/version.rb +3 -0
- data/lib/micro_bench.rb +70 -0
- data/spec/micro_bench/micro_bench_spec.rb +67 -0
- data/spec/spec_helper.rb +9 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4b772118be3419e0878ddf0f0cec08a83c67eefb
|
4
|
+
data.tar.gz: 1e08246f863d68db6434eeeb60ffd6bd8e04bc61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cc8cc8b61b6324d3fbb5a0e6d430b1dfbe057f7e23d802b4bf1094cb74795e49cf59461a9ed9431c96a17001d22383b8789079e2238c687e46437058f0914615
|
7
|
+
data.tar.gz: 1f6c2876766fec38271ef0245a9e9af48ee5fe5585e73435b2259dd70a0a8b752dfe439e7b28fcc6d560326bbe9337281f57825b89b547288f85b07dd5a6f9ca
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
|
2
|
+
# MicroBench
|
3
|
+
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/micro_bench.svg)](https://badge.fury.io/rb/micro_bench)
|
5
|
+
|
6
|
+
Ruby `Benchmark` module is nice but it uses blocks. We see 2 problems to it :
|
7
|
+
- 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.
|
9
|
+
|
10
|
+
Let's say you want to output the duration of `method_1` from :
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
foo = method_1
|
14
|
+
method_2(foo)
|
15
|
+
```
|
16
|
+
|
17
|
+
With `Benchmark`, we would write something like :
|
18
|
+
```ruby
|
19
|
+
foo = nil
|
20
|
+
duration = Benchmark.realtime do
|
21
|
+
foo = method_1
|
22
|
+
end
|
23
|
+
puts "Method 1 duration : #{duration} seconds"
|
24
|
+
method_2(foo)
|
25
|
+
```
|
26
|
+
|
27
|
+
With `MicroBench`, it will look like this :
|
28
|
+
```ruby
|
29
|
+
MicroBench.start
|
30
|
+
foo = method_1
|
31
|
+
puts "Method 1 duration : #{MicroBench.duration} seconds"
|
32
|
+
method_2(foo)
|
33
|
+
```
|
34
|
+
|
35
|
+
## Install
|
36
|
+
|
37
|
+
```
|
38
|
+
gem install micro_bench
|
39
|
+
```
|
40
|
+
|
41
|
+
or in Bundler:
|
42
|
+
```ruby
|
43
|
+
gem "micro_bench"
|
44
|
+
```
|
45
|
+
|
46
|
+
## Usage
|
47
|
+
|
48
|
+
### Basic usage
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require "micro_bench"
|
52
|
+
|
53
|
+
MicroBench.start
|
54
|
+
|
55
|
+
MicroBench.duration
|
56
|
+
# 1.628093000501394
|
57
|
+
|
58
|
+
MicroBench.duration
|
59
|
+
# 2.999483000487089
|
60
|
+
|
61
|
+
MicroBench.stop
|
62
|
+
# true
|
63
|
+
|
64
|
+
MicroBench.duration
|
65
|
+
# 5.4341670004651
|
66
|
+
|
67
|
+
MicroBench.duration
|
68
|
+
# 5.4341670004651
|
69
|
+
```
|
70
|
+
|
71
|
+
### Named benchmarks
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
require "micro_bench"
|
75
|
+
|
76
|
+
MicroBench.start("timer1")
|
77
|
+
|
78
|
+
MicroBench.stop("timer1")
|
79
|
+
|
80
|
+
MicroBench.duration("timer1")
|
81
|
+
# 1.628093000501394
|
82
|
+
```
|
83
|
+
|
84
|
+
### Thread safety
|
85
|
+
|
86
|
+
A benchmark is tied to a thread, ensuring that `MicroBench` is thread-safe. At the same time, it doesn't allow to share a benchmark between multiple threads.
|
87
|
+
|
88
|
+
### Multiple starts
|
89
|
+
|
90
|
+
Calling `.start` multiple times with the same `bench_id` will cause a "restart" of the given benchmark.
|
91
|
+
|
92
|
+
## Versioning
|
93
|
+
|
94
|
+
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).
|
95
|
+
|
96
|
+
## Authors
|
97
|
+
|
98
|
+
See the list of [contributors](https://github.com/klaxit/micro_bench/contributors) who participated in this project.
|
99
|
+
|
100
|
+
## License
|
101
|
+
|
102
|
+
Please see LICENSE
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class MicroBench::Benchmark
|
2
|
+
def initialize
|
3
|
+
@start_time = monotonic_clock_time
|
4
|
+
end
|
5
|
+
|
6
|
+
def stop
|
7
|
+
return false unless running?
|
8
|
+
|
9
|
+
@duration = monotonic_clock_time - @start_time
|
10
|
+
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
|
14
|
+
def duration
|
15
|
+
@duration || (monotonic_clock_time - @start_time)
|
16
|
+
end
|
17
|
+
|
18
|
+
def running?
|
19
|
+
@duration.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
duration.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def monotonic_clock_time
|
29
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
30
|
+
end
|
31
|
+
end
|
data/lib/micro_bench.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module MicroBench
|
2
|
+
class << self
|
3
|
+
# Start a benchmark
|
4
|
+
#
|
5
|
+
# == Parameters:
|
6
|
+
# bench_id::
|
7
|
+
# Identifier of the benchmark
|
8
|
+
#
|
9
|
+
# == Returns:
|
10
|
+
# A boolean representing success
|
11
|
+
#
|
12
|
+
# == Example usage:
|
13
|
+
# MicroBench.start(:my_benchmark)
|
14
|
+
#
|
15
|
+
# Calling the method multiple times with the same bench_id will restart
|
16
|
+
# the benchmark for the given bench_id.
|
17
|
+
#
|
18
|
+
def start(bench_id = nil)
|
19
|
+
benchmarks[benchmark_key(bench_id)] = MicroBench::Benchmark.new
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
|
23
|
+
# Stop a benchmark
|
24
|
+
#
|
25
|
+
# == Parameters:
|
26
|
+
# bench_id::
|
27
|
+
# Identifier of the benchmark
|
28
|
+
#
|
29
|
+
# == Returns:
|
30
|
+
# A boolean representing success
|
31
|
+
#
|
32
|
+
# == Example usage:
|
33
|
+
# MicroBench.stop(:my_benchmark)
|
34
|
+
#
|
35
|
+
def stop(bench_id = nil)
|
36
|
+
key = benchmark_key(bench_id)
|
37
|
+
return false unless benchmarks.key?(key)
|
38
|
+
|
39
|
+
benchmarks[key].stop
|
40
|
+
end
|
41
|
+
|
42
|
+
# Give duration of the benchmark
|
43
|
+
#
|
44
|
+
# == Parameters:
|
45
|
+
# bench_id::
|
46
|
+
# Identifier of the benchmark
|
47
|
+
#
|
48
|
+
# == Returns:
|
49
|
+
# Duration of the given benchmark, or nil if benchmark is unknown
|
50
|
+
#
|
51
|
+
# == Example usage:
|
52
|
+
# MicroBench.stop(:my_benchmark)
|
53
|
+
#
|
54
|
+
def duration(bench_id = nil)
|
55
|
+
benchmarks[benchmark_key(bench_id)]&.duration
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def benchmarks
|
61
|
+
@benchmarks ||= {}
|
62
|
+
end
|
63
|
+
|
64
|
+
def benchmark_key(bench_id = nil)
|
65
|
+
"#{Thread.current.object_id}||#{bench_id}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
require "micro_bench/benchmark"
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe MicroBench do
|
4
|
+
it "gives seconds duration doing something" do
|
5
|
+
described_class.start
|
6
|
+
sleep(0.01)
|
7
|
+
expect(
|
8
|
+
described_class.duration.round(2)
|
9
|
+
).to eq(0.01)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "allows to stop benchmark" do
|
13
|
+
described_class.start
|
14
|
+
sleep(0.01)
|
15
|
+
described_class.stop
|
16
|
+
sleep(0.02)
|
17
|
+
expect(
|
18
|
+
described_class.duration.round(2)
|
19
|
+
).to eq(0.01)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "restart each time 'start' is called" do
|
23
|
+
described_class.start
|
24
|
+
sleep(0.02)
|
25
|
+
described_class.start
|
26
|
+
sleep(0.01)
|
27
|
+
expect(
|
28
|
+
described_class.duration.round(2)
|
29
|
+
).to eq(0.01)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "allows multiple parallel named benchmarks" do
|
33
|
+
described_class.start(:bench1)
|
34
|
+
described_class.start(:bench2)
|
35
|
+
sleep(0.01)
|
36
|
+
described_class.stop(:bench1)
|
37
|
+
sleep(0.01)
|
38
|
+
described_class.stop(:bench2)
|
39
|
+
expect(
|
40
|
+
described_class.duration(:bench1).round(2)
|
41
|
+
).to eq(0.01)
|
42
|
+
expect(
|
43
|
+
described_class.duration(:bench2).round(2)
|
44
|
+
).to eq(0.01 * 2)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "is thread safe" do
|
48
|
+
t1 = Thread.new do
|
49
|
+
described_class.start
|
50
|
+
sleep(0.01)
|
51
|
+
described_class.stop
|
52
|
+
Thread.current[:expected] = 0.01
|
53
|
+
Thread.current[:duration] = described_class.duration
|
54
|
+
end
|
55
|
+
t2 = Thread.new do
|
56
|
+
described_class.start
|
57
|
+
sleep(0.01 * 2)
|
58
|
+
described_class.stop
|
59
|
+
Thread.current[:expected] = 0.01 * 2
|
60
|
+
Thread.current[:duration] = described_class.duration
|
61
|
+
end
|
62
|
+
[t1, t2].each do |t|
|
63
|
+
t.join
|
64
|
+
expect(t[:duration].round(2)).to eq(t[:expected])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: micro_bench
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cyrille Courtière
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: byebug
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '9.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '9.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.8'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.8'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- cyrille@klaxit.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- lib/micro_bench.rb
|
50
|
+
- lib/micro_bench/benchmark.rb
|
51
|
+
- lib/micro_bench/version.rb
|
52
|
+
- spec/micro_bench/micro_bench_spec.rb
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
homepage: http://github.com/klaxit/micro_bench
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.5.2.3
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Dead simple benchmarks
|
78
|
+
test_files:
|
79
|
+
- spec/micro_bench/micro_bench_spec.rb
|
80
|
+
- spec/spec_helper.rb
|