stable_profile 0.4.1 → 0.6.0

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
2
  SHA256:
3
- metadata.gz: 69f29fc4583e9a306a7aabbf1d9e267e924ea0be97ba6c3c592cc25899a9aa75
4
- data.tar.gz: aba44a7c4cc527a500c8e547aeda1d51944e1f2da271df0aec434967f88d6e00
3
+ metadata.gz: 924cfdff88d8cc5778394fdab96b6bf5e446d92e700e995aaddea7744fbf1eaf
4
+ data.tar.gz: d80755e9aa8810910baa570e9fca02db34efd52d3cad8bae22fb883f8c5ea2c5
5
5
  SHA512:
6
- metadata.gz: d1374fbf762bed4ec91bc9207cd225546480bf68d4b94ce978277905d18360ee992aacad83cc19a45444f39ed9481263c7a831774cccbe9ec0b21f01288c7777
7
- data.tar.gz: c761db15d550d213bc0d629874dc2f50acb693d58fba3b656eb841ae590d863f70fafb231bcbd82b37844ebf2ab5aa56a70724e3af0975a2b320b67224bb5773
6
+ metadata.gz: f1310ffc4a01c70433b737342d862e3de0540168dc43d1e237c4e0549b0376b675efb10435277ae65c15ebda335d25eaf20965b43587453ed742c6728f25959c
7
+ data.tar.gz: 9ab86cfbd9ec8194c645be23b35d94e3860da7f4a23f6967832cc82f5e84cc7dc4bb31138c4eeb05c403ee97557572b8a2b3fd38a0aaa936e9bac3daba8a82ac
@@ -4,9 +4,11 @@ require 'stable_profile'
4
4
 
5
5
  module StableProfile
6
6
  class CLI < Thor
7
- desc "profile", "Run RSpec profile with predictable results."
7
+ desc "profile", "Run RSpec profile multiple times, averaging the results."
8
+ method_option :iterations, aliases: "-i", type: :numeric, default: 20, desc: "Number of times to run RSpec"
9
+ method_option :top_slowest_examples, aliases: "-t", type: :numeric, default: 5, desc: "Number of slowest examples to output"
8
10
  def profile
9
- StableProfile.run
11
+ StableProfile.run(iterations: options[:iterations], top_slowest_examples: options[:top_slowest_examples])
10
12
  end
11
13
  default_task :profile
12
14
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'colorize'
3
4
  require 'fileutils'
4
5
  require 'json'
5
6
  require 'ruby-progressbar'
@@ -15,18 +16,8 @@ module StableProfile
15
16
  module_function
16
17
 
17
18
  # How many items to output in each category.
18
- TOP_SLOWEST_EXAMPLES = 5
19
-
20
- # The more iterations you run, the more accurate the results will be.
21
- # 20 seems like plenty, but it could take a while depending on the
22
- # size of your test suite.
23
- ITERATIONS = 4
24
-
25
- # It's a slow one if it showed up in at least half the profile runs.
26
- MINIMUM_SAMPLE_SIZE = ITERATIONS / 2
27
- DECIMAL_PLACES = 4
28
-
29
- OUTPUT_DIR = 'tmp/multi_profile'
19
+ DECIMAL_PLACES = 4
20
+ OUTPUT_DIR = 'tmp/stable_profile'
30
21
 
31
22
 
32
23
  def bold(string)
@@ -34,17 +25,17 @@ module StableProfile
34
25
  end
35
26
 
36
27
 
37
- def run
38
- puts "pwd = #{system('pwd')}"
28
+ def run(iterations:, top_slowest_examples:)
29
+ minimum_sample_size = iterations * 0.75
39
30
 
40
31
  # Erase and Create the output directory
41
32
  FileUtils.rm_rf(OUTPUT_DIR)
42
33
  FileUtils.mkdir_p(OUTPUT_DIR)
43
34
 
44
35
  # Run the specs ITERATIONS times, each time with a different random seed
45
- progressbar = ProgressBar.create(title: 'Running profiles', total: ITERATIONS, format: '%t: |%B| %p%% %a')
46
- ITERATIONS.times do |i|
47
- system("rspec --profile 50 --order random --format json > #{OUTPUT_DIR}/multi_profile_#{i+1}.json")
36
+ progressbar = ProgressBar.create(title: 'Running profiles', total: iterations, format: '%t: |%B| %p%% %a')
37
+ iterations.times do |i|
38
+ system("rspec --profile --order random --format json > #{OUTPUT_DIR}/multi_profile_#{i+1}.json")
48
39
  progressbar.increment
49
40
  end
50
41
 
@@ -82,30 +73,30 @@ module StableProfile
82
73
 
83
74
  # Mimic RSpec profile output
84
75
  puts
85
- puts "Top #{TOP_SLOWEST_EXAMPLES} slowest examples:"
76
+ puts "Top #{top_slowest_examples} slowest examples:"
86
77
  count = 0
87
78
  example_times.sort_by { |id, record| record[:average_time] }.reverse.each do |id, record|
88
79
  next if count == TOP_SLOWEST_EXAMPLES
89
- next if record[:run_times].size < MINIMUM_SAMPLE_SIZE
80
+ next if record[:run_times].size < minimum_sample_size
90
81
  count += 1
91
82
 
92
83
  example = record.fetch(:example)
93
84
 
94
- puts " #{example['full_description']}"
85
+ puts " #{example['full_description']}".colorize(:light_black)
95
86
  puts bold(" #{record[:average_time]} seconds").ljust(27) + " (N=#{record[:run_times].size})".ljust(7) + " #{example['file_path']}:#{example['line_number']}"
96
87
  end
97
88
 
98
89
  puts
99
- puts "Top #{TOP_SLOWEST_EXAMPLES} slowest example groups:"
90
+ puts "Top #{top_slowest_examples} slowest example groups:"
100
91
  count = 0
101
92
  group_times.sort_by { |id, record| record[:average_time] }.reverse.each do |id, record|
102
93
  next if count == TOP_SLOWEST_EXAMPLES
103
- next if record[:run_times].size < MINIMUM_SAMPLE_SIZE
94
+ next if record[:run_times].size < minimum_sample_size
104
95
  count += 1
105
96
 
106
97
  group = record.fetch(:group)
107
98
 
108
- puts " #{group['description']}"
99
+ puts " #{group['description']}".colorize(:light_black)
109
100
  puts bold(" #{record[:average_time]} seconds").ljust(27) + " (N=#{record[:run_times].size})".ljust(7) + " #{group['location']}"
110
101
  end
111
102
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stable_profile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robb Shecter
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-31 00:00:00.000000000 Z
11
+ date: 2023-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
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'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: ruby-progressbar
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +94,11 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: 3.12.0
83
- description: Repeatedly run --profile, averaging the results.
97
+ description: 'Solves a quirk of rspec --profile in some code bases: result vary with
98
+ every random spec ordering. This seems to be due to differences in dependency load
99
+ order, class initialization, and test server startup. This lib runs rspec --profile
100
+ many times, averaging the results to always give the same (stable) and meaningful
101
+ result.'
84
102
  email:
85
103
  - robb@public.law
86
104
  executables: