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 +4 -4
- data/Gemfile +4 -0
- data/Gemfile.lock +16 -10
- data/gem_footprint_analyzer.gemspec +0 -1
- data/lib/gem_footprint_analyzer/child_context.rb +2 -0
- data/lib/gem_footprint_analyzer/child_process.rb +5 -0
- data/lib/gem_footprint_analyzer/cli.rb +1 -0
- data/lib/gem_footprint_analyzer/cli/opts.rb +2 -0
- data/lib/gem_footprint_analyzer/cli/utils.rb +3 -0
- data/lib/gem_footprint_analyzer/core_ext/array.rb +1 -0
- data/lib/gem_footprint_analyzer/core_ext/file.rb +1 -0
- data/lib/gem_footprint_analyzer/core_ext/hash.rb +1 -0
- data/lib/gem_footprint_analyzer/formatters/json.rb +1 -0
- data/lib/gem_footprint_analyzer/formatters/tree.rb +8 -0
- data/lib/gem_footprint_analyzer/require_spy.rb +19 -1
- data/lib/gem_footprint_analyzer/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 222e0c4ea30e4a328897f79bb5c1bbd137b8fd5f063bbf9fe74bc697fbebbe76
|
4
|
+
data.tar.gz: d65e4e2b96459f029579244653a87761f137f21f43a6bdb56b456b2f2946923d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d18b017d780781fb892285df686cafd654d852f5ddb8b82b42ff221cc7ffb0651ae9b2d2e3ac1f4a22712e6d3b1296512fa2fcb5bb2f9532fdda8a0bf1da8349
|
7
|
+
data.tar.gz: 9eaad5508e6687e037d1ed49aa2e26ab81cc5e42b38804907b91a2661fecfc98f3554e9d7feb0e5341ff9c244a39eceb3348d9ee9418a73139a02c751f2a5340
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -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.
|
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
|
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
|
@@ -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
|
|
@@ -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
|
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.
|
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-
|
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
|