perflab 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 07770e966ab5d03af3ba434df0cab25aadf476862dd8d465c7a686394b34fecd
4
+ data.tar.gz: 0e5cff62571e62c0f7f3ad75e5bb27980e14b306b8271335cbf71033e32eae0e
5
+ SHA512:
6
+ metadata.gz: 34887275755092c94a09aea125fb946fd508e88216cdf8209b4d7791c12214d1040517eb1f1530896dc346f5439d36d9b0224f1897f7832a95b6b89dcf85958b
7
+ data.tar.gz: 839f89aeb9ba9d26d173a86ca36a1179133da63b67da621897a5b8858930b690cbbfa44effca278d4115275d93f81c19ff5efd095b79bb58a4e84baae44ff95a
@@ -0,0 +1,54 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ build:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.6.3-node
11
+
12
+ working_directory: ~/repo
13
+
14
+ steps:
15
+ - checkout
16
+
17
+ - run:
18
+ name: Configure Bundler
19
+ command: |
20
+ echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
21
+ source $BASH_ENV
22
+ gem install bundler
23
+
24
+ # Download and cache dependencies
25
+ - restore_cache:
26
+ keys:
27
+ - v1-dependencies-{{ checksum "Gemfile.lock" }}
28
+ # fallback to using the latest cache if no exact match is found
29
+ - v1-dependencies-
30
+
31
+ - run:
32
+ name: Install dependencies
33
+ command: |
34
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
35
+
36
+ - save_cache:
37
+ paths:
38
+ - ./vendor/bundle
39
+ key: v1-dependencies-{{ checksum "Gemfile.lock" }}
40
+
41
+ - run:
42
+ name: rubocop
43
+ command: bundle exec rubocop
44
+
45
+ - run:
46
+ name: rspec
47
+ command: bundle exec rspec
48
+
49
+ # collect reports
50
+ - store_test_results:
51
+ path: /tmp/test-results
52
+ - store_artifacts:
53
+ path: /tmp/test-results
54
+ destination: test-results
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ coverage
data/.rubocop.yml ADDED
@@ -0,0 +1,15 @@
1
+ Metrics/BlockLength:
2
+ Exclude:
3
+ - 'spec/*'
4
+
5
+ Metrics/LineLength:
6
+ Max: 130
7
+
8
+ Style/Documentation:
9
+ Enabled: false
10
+
11
+ Style/Semicolon:
12
+ Enabled: false
13
+
14
+ Style/TrivialAccessors:
15
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,90 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ perflab (0.1.0)
5
+ activesupport
6
+ benchmark-ipsa
7
+ stackprof
8
+ zeitwerk
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activesupport (5.2.3)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ ast (2.4.0)
19
+ benchmark-ips (2.5.0)
20
+ benchmark-ipsa (0.2.0)
21
+ benchmark-ips (~> 2.5.0)
22
+ memory_profiler (~> 0.9.6)
23
+ concurrent-ruby (1.1.5)
24
+ coveralls (0.8.23)
25
+ json (>= 1.8, < 3)
26
+ simplecov (~> 0.16.1)
27
+ term-ansicolor (~> 1.3)
28
+ thor (>= 0.19.4, < 2.0)
29
+ tins (~> 1.6)
30
+ diff-lcs (1.3)
31
+ docile (1.3.1)
32
+ i18n (1.6.0)
33
+ concurrent-ruby (~> 1.0)
34
+ jaro_winkler (1.5.2)
35
+ json (2.2.0)
36
+ memory_profiler (0.9.13)
37
+ minitest (5.11.3)
38
+ parallel (1.17.0)
39
+ parser (2.6.3.0)
40
+ ast (~> 2.4.0)
41
+ rainbow (3.0.0)
42
+ rspec (3.8.0)
43
+ rspec-core (~> 3.8.0)
44
+ rspec-expectations (~> 3.8.0)
45
+ rspec-mocks (~> 3.8.0)
46
+ rspec-core (3.8.0)
47
+ rspec-support (~> 3.8.0)
48
+ rspec-expectations (3.8.3)
49
+ diff-lcs (>= 1.2.0, < 2.0)
50
+ rspec-support (~> 3.8.0)
51
+ rspec-mocks (3.8.0)
52
+ diff-lcs (>= 1.2.0, < 2.0)
53
+ rspec-support (~> 3.8.0)
54
+ rspec-support (3.8.0)
55
+ rubocop (0.68.1)
56
+ jaro_winkler (~> 1.5.1)
57
+ parallel (~> 1.10)
58
+ parser (>= 2.5, != 2.5.1.1)
59
+ rainbow (>= 2.2.2, < 4.0)
60
+ ruby-progressbar (~> 1.7)
61
+ unicode-display_width (>= 1.4.0, < 1.6)
62
+ ruby-progressbar (1.10.0)
63
+ simplecov (0.16.1)
64
+ docile (~> 1.1)
65
+ json (>= 1.8, < 3)
66
+ simplecov-html (~> 0.10.0)
67
+ simplecov-html (0.10.2)
68
+ stackprof (0.2.12)
69
+ term-ansicolor (1.7.1)
70
+ tins (~> 1.0)
71
+ thor (0.20.3)
72
+ thread_safe (0.3.6)
73
+ tins (1.20.2)
74
+ tzinfo (1.2.5)
75
+ thread_safe (~> 0.1)
76
+ unicode-display_width (1.5.0)
77
+ zeitwerk (2.1.4)
78
+
79
+ PLATFORMS
80
+ ruby
81
+
82
+ DEPENDENCIES
83
+ coveralls
84
+ perflab!
85
+ rspec
86
+ rubocop
87
+ simplecov
88
+
89
+ BUNDLED WITH
90
+ 2.0.1
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright © 2019 Mert Guldur
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # PerfLab
2
+
3
+ [![CircleCI](https://circleci.com/gh/mertguldur/perflab.svg?style=svg)](https://circleci.com/gh/mertguldur/perflab)
4
+
5
+ ## Introduction
6
+
7
+ PerfLab is a unified interface for [stackprof](https://github.com/tmm1/stackprof), [benchmark](https://ruby-doc.org/stdlib-2.6.3/libdoc/benchmark/rdoc/Benchmark.html), [benchmark-ips](https://github.com/evanphx/benchmark-ips/) and [benchmark-ipsa](https://github.com/jondot/benchmark-ipsa) libraries. It allows performance testers to define code snippets they want to improve and benchmark against only once. It is designed to streamline the Profile -> Benchmark -> Iterate process.
8
+
9
+ ## Setup
10
+
11
+ Install [graphviz](https://www.graphviz.org/) to create dot graphs from profiler output files.
12
+
13
+ In your Gemfile:
14
+
15
+ ```ruby
16
+ gem 'perflab'
17
+ ```
18
+
19
+ Specify the code snippet you already have and the one you want to improve.
20
+
21
+ ```ruby
22
+ lab = PerfLab.configure do |config|
23
+ config.existing -> { MyService.slow_code }
24
+ config.improved -> { MyService.fast_code }
25
+ end
26
+ ```
27
+
28
+ ## Profiling
29
+
30
+ PerfLab uses `stackprof` to profile the given improved code snippet.
31
+
32
+ ```ruby
33
+ lab.profile # profiles the 'improved' snippet and writes to tmp/perflab/profiler.dump
34
+
35
+ lab.profile_existing # same as .profile except that it profiles the 'existing' snippet
36
+ ```
37
+
38
+ It is recommended to convert the dump file to a dot graph to easily interpret the report.
39
+
40
+ Bash example:
41
+
42
+ ```bash
43
+ function prof {
44
+ stackprof tmp/perflab/profiler.dump --graphviz > tmp/perflab/profiler.dot
45
+ dot -Tpng tmp/perflab/profiler.dot > tmp/perflab/profiler.png
46
+ open -a 'Google Chrome' tmp/perflab/profiler.png
47
+ }
48
+ ```
49
+
50
+ For other ways of examining the profiler report please refer to [stackprof](https://github.com/tmm1/stackprof).
51
+
52
+ ## Benchmarking
53
+
54
+ PerfLab provides wrappers for [Benchmark.bmbm](https://ruby-doc.org/stdlib-2.6.3/libdoc/benchmark/rdoc/Benchmark.html#method-c-bmbm), [Benchmark.ips](https://github.com/evanphx/benchmark-ips/) and [Benchmark.ipsa](https://github.com/jondot/benchmark-ipsa) methods.
55
+
56
+ ```ruby
57
+ lab.bmbm # calls Benchmark.bmbm with both
58
+ lab.bmbm_improved # calls Benchmark.bmbm with only improved
59
+
60
+ lab.ips # calls Benchmark.ips with both
61
+ lab.ips_improved # calls Benchmark.ips with only improved
62
+
63
+ lab.ipsa # calls Benchmark.ipsa with both
64
+ lab.ipsa_improved # calls Benchmark.ipsa with only improved
65
+ ```
66
+
67
+ It sets up `ips` and `ipsa` with one rehearsal round and favors `bmbm` over `bm` to minimize memory allocation and GC side effects.
68
+
69
+ ## Verifying correctness
70
+
71
+ PerfLab has a `correct?` method to verify that the `improved` snippet behaves exactly like `existing`.
72
+
73
+ ```ruby
74
+ lab.correct?
75
+ => # true or false
76
+ ```
77
+
78
+ By default it compares the return values of the snippets but one can pass in an `equality` lambda for additional checks.
79
+
80
+ ```ruby
81
+ lab = PerfLab.configure do |config|
82
+ config.existing -> { MyService.slow_code }
83
+ config.improved -> { MyService.fast_code }
84
+ config.equality ->(existing_result, improved_result) {
85
+ existing_result == improved_result && MyModel.count == 500
86
+ } # optional
87
+ end
88
+ ```
89
+
90
+ ## Thanks
91
+
92
+ This was written on [tastyworks'](https://tastyworks.com/) time.
data/lib/perflab.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'active_support/all'
2
+ require 'benchmark'
3
+ require 'benchmark/ipsa'
4
+ require 'stackprof'
5
+ require 'zeitwerk'
6
+
7
+ loader = Zeitwerk::Loader.for_gem
8
+ loader.setup
9
+ loader.eager_load
10
+
11
+ module PerfLab
12
+ module_function
13
+
14
+ def configure
15
+ config = Config.new
16
+ yield config
17
+ Operator.new(config.lambdas)
18
+ end
19
+ end
@@ -0,0 +1,51 @@
1
+ module PerfLab
2
+ class Benchmark
3
+ EXISTING = 'existing'.freeze
4
+ IMPROVED = 'improved'.freeze
5
+
6
+ class << self
7
+ def bmbm(improved, existing = nil)
8
+ results = ::Benchmark.bmbm do |x|
9
+ x.report(EXISTING) { existing.call } if existing.present?
10
+ x.report(IMPROVED) { improved.call }
11
+ end
12
+
13
+ return results unless existing.present?
14
+
15
+ print_bmbm_improvement(results)
16
+ results
17
+ end
18
+
19
+ def ips(improved, existing = nil)
20
+ ::Benchmark.ips do |x|
21
+ x.config(warmup: 1, time: 1)
22
+
23
+ x.report(EXISTING) { existing.call } if existing.present?
24
+ x.report(IMPROVED) { improved.call }
25
+
26
+ x.compare!
27
+ end
28
+ end
29
+
30
+ def ipsa(improved, existing = nil)
31
+ ::Benchmark.ipsa do |x|
32
+ x.config(warmup: 1, time: 1)
33
+
34
+ x.report(EXISTING) { existing.call } if existing.present?
35
+ x.report(IMPROVED) { improved.call }
36
+
37
+ x.compare!
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def print_bmbm_improvement(results)
44
+ existing_wall_time = results.find { |result| result.label == EXISTING }.real
45
+ improved_wall_time = results.find { |result| result.label == IMPROVED }.real
46
+
47
+ Util.print_performance_improvement(existing_wall_time, improved_wall_time)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ module PerfLab
2
+ class Config
3
+ def existing(existing)
4
+ @existing = existing
5
+ end
6
+
7
+ def improved(improved)
8
+ @improved = improved
9
+ end
10
+
11
+ def equality(equality)
12
+ @equality = equality
13
+ end
14
+
15
+ def lambdas
16
+ {
17
+ existing: @existing,
18
+ improved: @improved,
19
+ equality: @equality
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,60 @@
1
+ module PerfLab
2
+ class Operator
3
+ def initialize(existing:, improved:, equality:)
4
+ @existing = existing
5
+ @improved = improved
6
+ @equality = equality
7
+ end
8
+
9
+ def profile
10
+ puts 'Rehearsal...'
11
+ @improved.call
12
+
13
+ puts 'Profiling...'
14
+ Profiler.profile(@improved)
15
+ end
16
+
17
+ def profile_existing
18
+ puts 'Rehearsal...'
19
+ @existing.call
20
+
21
+ puts 'Profiling...'
22
+ Profiler.profile(@existing)
23
+ end
24
+
25
+ def bmbm
26
+ Benchmark.bmbm(@improved, @existing)
27
+ end
28
+
29
+ def bmbm_improved
30
+ Benchmark.bmbm(@improved)
31
+ end
32
+
33
+ def ips
34
+ Benchmark.ips(@improved, @existing)
35
+ end
36
+
37
+ def ips_improved
38
+ Benchmark.ipsa(@improved)
39
+ end
40
+
41
+ def ipsa
42
+ Benchmark.ipsa(@improved, @existing)
43
+ end
44
+
45
+ def ipsa_improved
46
+ Benchmark.ipsa(@improved)
47
+ end
48
+
49
+ def correct?
50
+ if @equality.present?
51
+ result = @equality.call(@existing.call, @improved.call)
52
+ raise ArgumentError, 'Equality must return a boolean' unless [TrueClass, FalseClass].include?(result.class)
53
+
54
+ result
55
+ else
56
+ @existing.call == @improved.call
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,15 @@
1
+ module PerfLab
2
+ class Profiler
3
+ DIRECTORY = 'tmp/perflab'.freeze
4
+ FILENAME = 'profiler.dump'.freeze
5
+
6
+ class << self
7
+ def profile(lambda)
8
+ FileUtils.mkdir_p(DIRECTORY)
9
+ path = "#{DIRECTORY}/#{FILENAME}"
10
+
11
+ StackProf.run(mode: :wall, out: path, raw: true) { lambda.call }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module PerfLab
2
+ class Util
3
+ class << self
4
+ def print_performance_improvement(existing_result, improved_result)
5
+ percentage = ((improved_result.to_f - existing_result.to_f) / existing_result.to_f) * 100
6
+
7
+ if percentage < 0
8
+ puts "Improved is #{percentage.abs.round(2)}% faster"
9
+ elsif percentage > 0
10
+ puts "Improved is #{percentage.abs.round(2)}% slower"
11
+ else
12
+ puts 'No difference in speed'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
data/perflab.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'perflab'
3
+ s.version = '0.1.0'
4
+ s.date = '2019-05-08'
5
+ s.summary = 'Ruby performance lab'
6
+ s.description = 'Library to profile and benchmark Ruby code'
7
+ s.authors = ['Mert Guldur']
8
+ s.email = 'mertguldur@gmail.com'
9
+ s.files = `git ls-files`.split("\n")
10
+ s.license = 'MIT'
11
+
12
+ s.add_dependency 'activesupport'
13
+ s.add_dependency 'benchmark-ipsa'
14
+ s.add_dependency 'stackprof'
15
+ s.add_dependency 'zeitwerk'
16
+
17
+ s.add_development_dependency 'coveralls'
18
+ s.add_development_dependency 'rspec'
19
+ s.add_development_dependency 'rubocop'
20
+ s.add_development_dependency 'simplecov'
21
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ describe PerfLab do
4
+ let(:lab) do
5
+ described_class.configure do |config|
6
+ config.existing -> { 100.times; 100 }
7
+ config.improved -> { 10.times; 10 }
8
+ config.equality ->(_existing_result, _improved_result) { true }
9
+ end
10
+ end
11
+
12
+ describe 'profiling' do
13
+ let(:directory) { 'spec' }
14
+ let(:filename) { 'perflab-profiler-test.dump' }
15
+ let(:path) { "#{directory}/#{filename}" }
16
+
17
+ before do
18
+ stub_const('PerfLab::Profiler::DIRECTORY', directory)
19
+ stub_const('PerfLab::Profiler::FILENAME', filename)
20
+ end
21
+
22
+ describe '.profile' do
23
+ it 'profiles the improved lambda and creates an output file' do
24
+ lab.profile
25
+
26
+ expect(File.exist?(path)).to eq(true)
27
+ end
28
+ end
29
+
30
+ describe '.profile_existing' do
31
+ it 'profiles the existing lambda and creates an output file' do
32
+ lab.profile_existing
33
+
34
+ expect(File.exist?(path)).to eq(true)
35
+ end
36
+ end
37
+
38
+ after do
39
+ FileUtils.rm(path)
40
+ end
41
+ end
42
+
43
+ describe '.bmbm' do
44
+ it 'creates a benchmark with existing and improved lambdas' do
45
+ results = lab.bmbm
46
+
47
+ expect(results.size).to eq(2)
48
+ results.each do |result|
49
+ expect(result).to be_a(Benchmark::Tms)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '.bmbm_improved' do
55
+ it 'creates a benchmark only with the improved lambda' do
56
+ results = lab.bmbm_improved
57
+
58
+ expect(results.size).to eq(1)
59
+ expect(results.first).to be_a(Benchmark::Tms)
60
+ end
61
+ end
62
+
63
+ describe '.ips' do
64
+ it 'creates a benchmark with existing and improved lambdas' do
65
+ result = lab.ips
66
+ expect(result).to be_a(Benchmark::IPS::Report)
67
+ end
68
+ end
69
+
70
+ describe '.ips_improved' do
71
+ it 'creates a benchmark only with improved lambda' do
72
+ result = lab.ips_improved
73
+ expect(result).to be_a(Benchmark::IPS::Report)
74
+ end
75
+ end
76
+
77
+ describe '.ipsa' do
78
+ it 'creates a benchmark with existing and improved lambdas' do
79
+ result = lab.ipsa
80
+ expect(result).to be_a(Benchmark::IPS::Report)
81
+ end
82
+ end
83
+
84
+ describe '.ipsa_improved' do
85
+ it 'creates a benchmark only with improved lambda' do
86
+ result = lab.ipsa_improved
87
+ expect(result).to be_a(Benchmark::IPS::Report)
88
+ end
89
+ end
90
+
91
+ describe 'equality' do
92
+ context 'when the equality is provided' do
93
+ it 'runs the lambda to verify correctness' do
94
+ expect(lab).to be_correct
95
+ end
96
+ end
97
+
98
+ context 'when the equality is not provided' do
99
+ it 'compares the return values of the existing and improved lambdas to verify correctness' do
100
+ lab = described_class.configure do |config|
101
+ config.existing -> { 100.times; 100 }
102
+ config.improved -> { 10.times; 10 }
103
+ end
104
+
105
+ expect(lab).to_not be_correct
106
+ end
107
+ end
108
+ end
109
+
110
+ describe 'performance improvement calculation' do
111
+ context 'when improved is faster' do
112
+ it 'prints a message saying improved is faster' do
113
+ described_class::Util.print_performance_improvement(10, 5)
114
+ end
115
+ end
116
+
117
+ context 'when improved is slower' do
118
+ it 'prints a message saying improved is slower' do
119
+ described_class::Util.print_performance_improvement(10, 15)
120
+ end
121
+ end
122
+
123
+ context 'when there is not difference' do
124
+ it 'prints a message saying there is no difference' do
125
+ described_class::Util.print_performance_improvement(10, 10)
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,11 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ Coveralls::SimpleCov::Formatter,
6
+ SimpleCov::Formatter::HTMLFormatter,
7
+ ]
8
+
9
+ SimpleCov.start
10
+
11
+ require 'perflab'
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perflab
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mert Guldur
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: benchmark-ipsa
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: stackprof
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: zeitwerk
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Library to profile and benchmark Ruby code
126
+ email: mertguldur@gmail.com
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files: []
130
+ files:
131
+ - ".circleci/config.yml"
132
+ - ".gitignore"
133
+ - ".rubocop.yml"
134
+ - Gemfile
135
+ - Gemfile.lock
136
+ - LICENSE.txt
137
+ - README.md
138
+ - lib/perflab.rb
139
+ - lib/perflab/benchmark.rb
140
+ - lib/perflab/config.rb
141
+ - lib/perflab/operator.rb
142
+ - lib/perflab/profiler.rb
143
+ - lib/perflab/util.rb
144
+ - perflab.gemspec
145
+ - spec/perflab_spec.rb
146
+ - spec/spec_helper.rb
147
+ homepage:
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.7.6
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: Ruby performance lab
171
+ test_files: []