gem_footprint_analyzer 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13ad6f4a90d9f22d88152496807371138eecc8456b195ecf63597771c3e5f43d
4
- data.tar.gz: 6f78c45ebac12fb4602c61d3ff59b71b9c8dc0dff0fb88a7344ce56506e0c4f1
3
+ metadata.gz: 222e0c4ea30e4a328897f79bb5c1bbd137b8fd5f063bbf9fe74bc697fbebbe76
4
+ data.tar.gz: d65e4e2b96459f029579244653a87761f137f21f43a6bdb56b456b2f2946923d
5
5
  SHA512:
6
- metadata.gz: 5aa544dacfe1ac6d74622d07ed884e92ddeb40203f460701a2afe05f691bd0df2d495bac22efb3dba8b32d0b678e925ede6d00fbfaf66fe1fcef472c541f83b0
7
- data.tar.gz: 52ee797d7c5a24d16effc451eb9d64b5bfd577601767e2efd974d9b7fe013cddceca41d9d89aaffcefb7931f8ac75920869a63fb53e89696dc97b4d169e64459
6
+ metadata.gz: d18b017d780781fb892285df686cafd654d852f5ddb8b82b42ff221cc7ffb0651ae9b2d2e3ac1f4a22712e6d3b1296512fa2fcb5bb2f9532fdda8a0bf1da8349
7
+ data.tar.gz: 9eaad5508e6687e037d1ed49aa2e26ab81cc5e42b38804907b91a2661fecfc98f3554e9d7feb0e5341ff9c244a39eceb3348d9ee9418a73139a02c751f2a5340
data/Gemfile CHANGED
@@ -5,3 +5,7 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
5
5
  # Specify your gem's dependencies in gem_footprint_analyzer.gemspec
6
6
  gemspec
7
7
 
8
+ group :development do
9
+ gem 'rubocop', github: 'rubocop-hq/rubocop', branch: 'master'
10
+ end
11
+
@@ -1,7 +1,21 @@
1
+ GIT
2
+ remote: https://github.com/rubocop-hq/rubocop
3
+ revision: aa2c86fd45463acd2818650898771bd9bed8731b
4
+ branch: master
5
+ specs:
6
+ rubocop (0.60.0)
7
+ jaro_winkler (~> 1.5.1)
8
+ parallel (~> 1.10)
9
+ parser (>= 2.5, != 2.5.1.1)
10
+ powerpack (~> 0.1)
11
+ rainbow (>= 2.2.2, < 4.0)
12
+ ruby-progressbar (~> 1.7)
13
+ unicode-display_width (~> 1.4.0)
14
+
1
15
  PATH
2
16
  remote: .
3
17
  specs:
4
- gem_footprint_analyzer (0.1.7)
18
+ gem_footprint_analyzer (0.1.8)
5
19
 
6
20
  GEM
7
21
  remote: https://rubygems.org/
@@ -28,14 +42,6 @@ GEM
28
42
  diff-lcs (>= 1.2.0, < 2.0)
29
43
  rspec-support (~> 3.8.0)
30
44
  rspec-support (3.8.0)
31
- rubocop (0.60.0)
32
- jaro_winkler (~> 1.5.1)
33
- parallel (~> 1.10)
34
- parser (>= 2.5, != 2.5.1.1)
35
- powerpack (~> 0.1)
36
- rainbow (>= 2.2.2, < 4.0)
37
- ruby-progressbar (~> 1.7)
38
- unicode-display_width (~> 1.4.0)
39
45
  rubocop-rspec (1.30.1)
40
46
  rubocop (>= 0.60.0)
41
47
  ruby-progressbar (1.10.0)
@@ -49,7 +55,7 @@ DEPENDENCIES
49
55
  gem_footprint_analyzer!
50
56
  rake (~> 10.0)
51
57
  rspec (~> 3.0)
52
- rubocop (~> 0.60.0)
58
+ rubocop!
53
59
  rubocop-rspec (~> 1.30)
54
60
 
55
61
  BUNDLED WITH
@@ -26,6 +26,5 @@ Gem::Specification.new do |spec|
26
26
  spec.add_development_dependency "bundler", "~> 1.16"
27
27
  spec.add_development_dependency "rake", "~> 10.0"
28
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
- spec.add_development_dependency "rubocop", "~> 0.60.0"
30
29
  spec.add_development_dependency "rubocop-rspec", "~> 1.30"
31
30
  end
@@ -9,6 +9,8 @@ module GemFootprintAnalyzer
9
9
  PARENT_FIFO = '/tmp/parent'.freeze
10
10
  CHILD_FIFO = '/tmp/child'.freeze
11
11
 
12
+ # Prints the process pid, so it can be grabbed by the supervisor process, inits tranport fifos
13
+ # and requires requested libraries.
12
14
  def initialize
13
15
  output Process.pid
14
16
  init_transport
@@ -7,6 +7,7 @@ module GemFootprintAnalyzer
7
7
  LEGACY_RUBY_CMD = [RbConfig.ruby, '--disable=gem'].freeze
8
8
  RUBY_CMD = [RbConfig.ruby, '--disable=did_you_mean', '--disable=gem'].freeze
9
9
 
10
+ # Sets necessary ivars
10
11
  def initialize(library, require_string, fifos, options = {})
11
12
  @library = library
12
13
  @require_string = require_string || library
@@ -15,6 +16,8 @@ module GemFootprintAnalyzer
15
16
  @options = options
16
17
  end
17
18
 
19
+ # Starts a child process in a child-watching-thread
20
+ # Reads it's PID from the new process' STDOUT and sets it as an instance variable
18
21
  def start_child
19
22
  @child_thread ||= Thread.new do # rubocop:disable Naming/MemoizedInstanceVariableName
20
23
  Open3.popen3(child_env_vars, *ruby_command, context_file) do |_, stdout, stderr|
@@ -27,6 +30,8 @@ module GemFootprintAnalyzer
27
30
  end
28
31
  end
29
32
 
33
+ # Blocking method
34
+ # @return [Integer|nil] Process id or nil, if the child-watching-thread is not started
30
35
  def pid
31
36
  return unless child_thread
32
37
 
@@ -4,6 +4,7 @@ module GemFootprintAnalyzer
4
4
  # A command line interface class for the gem.
5
5
  # Provides options parsing and help messages for the user.
6
6
  class CLI
7
+ # Sets default options, to be overwritten by option parser down the road
7
8
  def initialize
8
9
  @options = {}
9
10
  @options[:runs] = 10
@@ -57,6 +57,8 @@ module GemFootprintAnalyzer
57
57
 
58
58
  attr_reader :options
59
59
 
60
+ private
61
+
60
62
  def banner
61
63
  script_name = "bundle exec #{File.basename($PROGRAM_NAME)}"
62
64
 
@@ -2,6 +2,9 @@ module GemFootprintAnalyzer
2
2
  class CLI
3
3
  # A module containing helper methods for CLI
4
4
  module Utils
5
+ # Outputs strings to STDOUT, in case it's no longer possible (ex. when piped to head),
6
+ # it exits the process.
7
+ # @param output [String] message to be outputted to STDOUT
5
8
  def self.safe_puts(output)
6
9
  output ||= "\n"
7
10
 
@@ -2,6 +2,7 @@ module GemFootprintAnalyzer
2
2
  module CoreExt
3
3
  # Provides Array#sum, missing in Ruby 2.2.0
4
4
  module Array
5
+ # Sums over the array
5
6
  def sum(init = 0, &block)
6
7
  if block
7
8
  reduce(init) { |acc, el| acc + yield(el) }
@@ -2,6 +2,7 @@ module GemFootprintAnalyzer
2
2
  module CoreExt
3
3
  # Provides File#mkfifo, missing in Ruby 2.2.0
4
4
  module File
5
+ # @param name [String] Name of the fifo file to be created
5
6
  def mkfifo(name)
6
7
  system("mkfifo #{name}") || fail('Failed to make FIFO special file')
7
8
  end
@@ -2,6 +2,7 @@ module GemFootprintAnalyzer
2
2
  module CoreExt
3
3
  # Provides Hash#dig, missing in Ruby 2.2.0
4
4
  module Hash
5
+ # @param keys [Array<Symbol|String>] list of keys to dig from the hash
5
6
  def dig(*keys)
6
7
  value = self
7
8
  keys.each do |key|
@@ -3,6 +3,7 @@ module GemFootprintAnalyzer
3
3
  # A formatter class outputting bare JSON.
4
4
  # Useful for integrating with other tools.
5
5
  class Json
6
+ # Initializer conforms to formatters interface
6
7
  def initialize(*); end
7
8
 
8
9
  # @return [String] A JSON form of the requires_list array, last entry is the cumulated result.
@@ -9,33 +9,41 @@ module GemFootprintAnalyzer
9
9
  class Entry
10
10
  BUNDLER_RUNTIME = 'bundler/runtime'.freeze
11
11
 
12
+ # @param entry_hash [Hash<Symbol>] Hash with a single require analysis
13
+ # @param options [Hash<Symbol>]
12
14
  def initialize(entry_hash, options = {})
13
15
  @entry_hash = entry_hash
14
16
  @options = options
15
17
  end
16
18
 
19
+ # @return [String] Require name
17
20
  def name
18
21
  @entry_hash[:name]
19
22
  end
20
23
 
24
+ # @return [String] Formatted parent require name
21
25
  def parent
22
26
  @entry_hash[:parent_name]
23
27
  end
24
28
 
29
+ # @return [Integer] Formatted time value
25
30
  def time
26
31
  time = @entry_hash.dig(:time, :mean)
27
32
  time && time.round
28
33
  end
29
34
 
35
+ # @return [Integer] Formatted RSS value
30
36
  def rss
31
37
  rss = @entry_hash.dig(:rss, :mean)
32
38
  rss && rss.round
33
39
  end
34
40
 
41
+ # @return [String] Formatted require name
35
42
  def formatted_name
36
43
  "#{name}#{debug_parent}"
37
44
  end
38
45
 
46
+ # @return [Bool] Is the entry a Gem or original require to be analyzed
39
47
  def top_level?
40
48
  parent.nil? || parent == BUNDLER_RUNTIME
41
49
  end
@@ -7,6 +7,9 @@ module GemFootprintAnalyzer
7
7
  %r{active_support/dependencies\.rb.+(`require'|`load_dependency'|`block in require')\z}.freeze
8
8
 
9
9
  class << self
10
+ # @param caller_entry [String] A single stack frame
11
+ # @param require_name [String|nil] An optional require name to calculate full_path from
12
+ # @return [String] path relative to the gem lib directory
10
13
  def relative_path(caller_entry, require_name = nil)
11
14
  caller_file = caller_entry.split(':')[0]
12
15
  if require_name
@@ -19,14 +22,19 @@ module GemFootprintAnalyzer
19
22
  full_path.sub(%r{\A#{load_path}/}, '')
20
23
  end
21
24
 
25
+ # @return [Array<String>] All configured load paths in the full directory form
22
26
  def load_paths
23
27
  @load_paths ||= $LOAD_PATH.map { |path| File.expand_path(path) }
24
28
  end
25
29
 
30
+ # @param name [String] require name
31
+ # @return [String] name with the .rb extension truncated
26
32
  def without_extension(name)
27
33
  name.sub(/\.rb\z/, '')
28
34
  end
29
35
 
36
+ # @param [Array<String>] List of caller stack frames
37
+ # @return [String|nil] First caller entry that doesn't originate from this gem
30
38
  def first_foreign_caller(caller_list)
31
39
  ffc = caller_list.find do |c|
32
40
  c !~ ACTIVESUPPORT_REQUIRE_DEPENDENCY &&
@@ -35,6 +43,7 @@ module GemFootprintAnalyzer
35
43
  without_extension(relative_path(ffc)) if ffc
36
44
  end
37
45
 
46
+ # Installs require spying on all relevant methods
38
47
  def spy_require(transport)
39
48
  alias_require_methods
40
49
 
@@ -42,6 +51,7 @@ module GemFootprintAnalyzer
42
51
  define_requires(transport)
43
52
  end
44
53
 
54
+ # @return [Array] Tuple with method call duration and return value
45
55
  def timed_exec
46
56
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
47
57
  result = yield
@@ -49,6 +59,7 @@ module GemFootprintAnalyzer
49
59
  [duration, result]
50
60
  end
51
61
 
62
+ # Aliases original methods, so they are accessible from methods that shadow them
52
63
  def alias_require_methods
53
64
  kernels.each do |k|
54
65
  k.send :alias_method, :regular_require, :require
@@ -56,14 +67,19 @@ module GemFootprintAnalyzer
56
67
  end
57
68
  end
58
69
 
70
+ # @return [Array<Class>] CLasses that have require* methods that we'll spy on
59
71
  def kernels
60
72
  @kernels ||= [(class << ::Kernel; self; end), Kernel]
61
73
  end
62
74
 
75
+ # @param transport [Transport] Instance of transport to be used by the require proxy method
63
76
  def define_requires(transport)
64
77
  kernels.each { |k| define_require(k, transport) }
65
78
  end
66
79
 
80
+ # @param klass [Class] Target class to have the spying require defined
81
+ # @param transport [Transport] Instance of transport to be used by the require proxy method
82
+ # Replaces require methods with proxied versions
67
83
  def define_require(klass, transport)
68
84
  klass.send :define_method, :require do |name|
69
85
  transport.ready_and_wait_for_start
@@ -78,6 +94,7 @@ module GemFootprintAnalyzer
78
94
  end
79
95
  end
80
96
 
97
+ # Replaces require_relative methods with proxied versions
81
98
  def define_require_relatives
82
99
  # As of Ruby 2.5.1, both :require and :require_relative use an unexposed native method
83
100
  # rb_safe_require, however it's challenging to plug into it and using original
@@ -85,9 +102,10 @@ module GemFootprintAnalyzer
85
102
  # we're redirecting :require_relative to the regular :require
86
103
  kernels.each do |k|
87
104
  k.send :define_method, :require_relative do |name|
105
+ return require(name) if name.start_with?('/')
106
+
88
107
  last_caller = caller(1..1).first
89
108
  relative_path = GemFootprintAnalyzer::RequireSpy.relative_path(last_caller, name)
90
-
91
109
  require(relative_path)
92
110
  end
93
111
  end
@@ -1,3 +1,3 @@
1
1
  module GemFootprintAnalyzer
2
- VERSION = '0.1.7'.freeze
2
+ VERSION = '0.1.8'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gem_footprint_analyzer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciek Dubiński
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-24 00:00:00.000000000 Z
11
+ date: 2018-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 0.60.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 0.60.0
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rubocop-rspec
71
57
  requirement: !ruby/object:Gem::Requirement