profile 0.4.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 89b239c449c5e0c5ba1806075b167dd3cb3be09819936abc723e46bab1d93341
4
+ data.tar.gz: c49ab1d4bd239002a8671116d119b1395f9d1503edc11ad96931c3abb98d9f1c
5
+ SHA512:
6
+ metadata.gz: 4ad235224dde987ebfbecd3c654e6181423b4ce661ca59ded8d001e8d00f03e9fdeb42e294aa056bbe5501efbcd5a1710876aaf62ea5c938e391861a7c0b6390
7
+ data.tar.gz: f4a666e2779dce2d6e5f4c33bb53728d4d5c53771f1ac167445422389488fc59acdb0ab3762177443065fc81b16b17ec48f22c185afd32c558a81cee4ce31a4f
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in profile.gemspec
4
+ gemspec
@@ -0,0 +1,96 @@
1
+ # Profile
2
+
3
+ Profile provides a way to Profile your Ruby application.
4
+
5
+ Profiling your program is a way of determining which methods are called and
6
+ how long each method takes to complete. This way you can detect which
7
+ methods are possible bottlenecks.
8
+
9
+ Profiling your program will slow down your execution time considerably,
10
+ so activate it only when you need it. Don't confuse benchmarking with
11
+ profiling.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'profile'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install profile
28
+
29
+ ## Usage
30
+
31
+ There are two ways to activate Profiling:
32
+
33
+ ### Command line
34
+
35
+ Run your Ruby script with <code>-rprofile</code>:
36
+
37
+ ```bash
38
+ $ ruby -rprofile example.rb
39
+ ```
40
+
41
+ If you're profiling an executable in your <code>$PATH</code> you can use
42
+ <code>ruby -S</code>:
43
+
44
+ ```bash
45
+ $ ruby -rprofile -S some_executable
46
+ ```
47
+
48
+ ### From code
49
+
50
+ Just require 'profile':
51
+
52
+ ```ruby
53
+ require 'profile'
54
+
55
+ def slow_method
56
+ 5000.times do
57
+ 9999999999999999*999999999
58
+ end
59
+ end
60
+
61
+ def fast_method
62
+ 5000.times do
63
+ 9999999999999999+999999999
64
+ end
65
+ end
66
+
67
+ slow_method
68
+ fast_method
69
+ ```
70
+
71
+ The output in both cases is a report when the execution is over:
72
+
73
+ ```
74
+ $ ruby -rprofile example.rb
75
+
76
+ % cumulative self self total
77
+ time seconds seconds calls ms/call ms/call name
78
+ 68.42 0.13 0.13 2 65.00 95.00 Integer#times
79
+ 15.79 0.16 0.03 5000 0.01 0.01 Fixnum#*
80
+ 15.79 0.19 0.03 5000 0.01 0.01 Fixnum#+
81
+ 0.00 0.19 0.00 2 0.00 0.00 IO#set_encoding
82
+ 0.00 0.19 0.00 1 0.00 100.00 Object#slow_method
83
+ 0.00 0.19 0.00 2 0.00 0.00 Module#method_added
84
+ 0.00 0.19 0.00 1 0.00 90.00 Object#fast_method
85
+ 0.00 0.19 0.00 1 0.00 190.00 #toplevel
86
+ ```
87
+
88
+ ## Development
89
+
90
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
91
+
92
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
93
+
94
+ ## Contributing
95
+
96
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/profile.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "profile"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ require 'profiler'
3
+
4
+ RubyVM::InstructionSequence.compile_option = {
5
+ :trace_instruction => true,
6
+ :specialized_instruction => false
7
+ }
8
+ END {
9
+ Profiler__::print_profile(STDERR)
10
+ }
11
+ Profiler__::start_profile
@@ -0,0 +1,3 @@
1
+ module Profile
2
+ VERSION = "0.4.0"
3
+ end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+ # Profile provides a way to Profile your Ruby application.
3
+ #
4
+ # Profiling your program is a way of determining which methods are called and
5
+ # how long each method takes to complete. This way you can detect which
6
+ # methods are possible bottlenecks.
7
+ #
8
+ # Profiling your program will slow down your execution time considerably,
9
+ # so activate it only when you need it. Don't confuse benchmarking with
10
+ # profiling.
11
+ #
12
+ # There are two ways to activate Profiling:
13
+ #
14
+ # == Command line
15
+ #
16
+ # Run your Ruby script with <code>-rprofile</code>:
17
+ #
18
+ # ruby -rprofile example.rb
19
+ #
20
+ # If you're profiling an executable in your <code>$PATH</code> you can use
21
+ # <code>ruby -S</code>:
22
+ #
23
+ # ruby -rprofile -S some_executable
24
+ #
25
+ # == From code
26
+ #
27
+ # Just require 'profile':
28
+ #
29
+ # require 'profile'
30
+ #
31
+ # def slow_method
32
+ # 5000.times do
33
+ # 9999999999999999*999999999
34
+ # end
35
+ # end
36
+ #
37
+ # def fast_method
38
+ # 5000.times do
39
+ # 9999999999999999+999999999
40
+ # end
41
+ # end
42
+ #
43
+ # slow_method
44
+ # fast_method
45
+ #
46
+ # The output in both cases is a report when the execution is over:
47
+ #
48
+ # ruby -rprofile example.rb
49
+ #
50
+ # % cumulative self self total
51
+ # time seconds seconds calls ms/call ms/call name
52
+ # 68.42 0.13 0.13 2 65.00 95.00 Integer#times
53
+ # 15.79 0.16 0.03 5000 0.01 0.01 Fixnum#*
54
+ # 15.79 0.19 0.03 5000 0.01 0.01 Fixnum#+
55
+ # 0.00 0.19 0.00 2 0.00 0.00 IO#set_encoding
56
+ # 0.00 0.19 0.00 1 0.00 100.00 Object#slow_method
57
+ # 0.00 0.19 0.00 2 0.00 0.00 Module#method_added
58
+ # 0.00 0.19 0.00 1 0.00 90.00 Object#fast_method
59
+ # 0.00 0.19 0.00 1 0.00 190.00 #toplevel
60
+
61
+ module Profiler__
62
+ class Wrapper < Struct.new(:defined_class, :method_id, :hash) # :nodoc:
63
+ private :defined_class=, :method_id=, :hash=
64
+
65
+ def initialize(klass, mid)
66
+ super(klass, mid, nil)
67
+ self.hash = Struct.instance_method(:hash).bind(self).call
68
+ end
69
+
70
+ def to_s
71
+ "#{defined_class.inspect}#".sub(/\A\#<Class:(.*)>#\z/, '\1.') << method_id.to_s
72
+ end
73
+ alias inspect to_s
74
+ end
75
+
76
+ # internal values
77
+ @@start = nil # the start time that profiling began
78
+ @@stacks = nil # the map of stacks keyed by thread
79
+ @@maps = nil # the map of call data keyed by thread, class and id. Call data contains the call count, total time,
80
+ PROFILE_CALL_PROC = TracePoint.new(*%i[call c_call b_call]) {|tp| # :nodoc:
81
+ now = Process.times[0]
82
+ stack = (@@stacks[Thread.current] ||= [])
83
+ stack.push [now, 0.0]
84
+ }
85
+ PROFILE_RETURN_PROC = TracePoint.new(*%i[return c_return b_return]) {|tp| # :nodoc:
86
+ now = Process.times[0]
87
+ key = Wrapper.new(tp.defined_class, tp.method_id)
88
+ stack = (@@stacks[Thread.current] ||= [])
89
+ if tick = stack.pop
90
+ threadmap = (@@maps[Thread.current] ||= {})
91
+ data = (threadmap[key] ||= [0, 0.0, 0.0, key])
92
+ data[0] += 1
93
+ cost = now - tick[0]
94
+ data[1] += cost
95
+ data[2] += cost - tick[1]
96
+ stack[-1][1] += cost if stack[-1]
97
+ end
98
+ }
99
+ module_function
100
+ # Starts the profiler.
101
+ #
102
+ # See Profiler__ for more information.
103
+ def start_profile
104
+ @@start = Process.times[0]
105
+ @@stacks = {}
106
+ @@maps = {}
107
+ PROFILE_CALL_PROC.enable
108
+ PROFILE_RETURN_PROC.enable
109
+ end
110
+ # Stops the profiler.
111
+ #
112
+ # See Profiler__ for more information.
113
+ def stop_profile
114
+ PROFILE_CALL_PROC.disable
115
+ PROFILE_RETURN_PROC.disable
116
+ end
117
+ # Outputs the results from the profiler.
118
+ #
119
+ # See Profiler__ for more information.
120
+ def print_profile(f)
121
+ stop_profile
122
+ total = Process.times[0] - @@start
123
+ if total == 0 then total = 0.01 end
124
+ totals = {}
125
+ @@maps.values.each do |threadmap|
126
+ threadmap.each do |key, data|
127
+ total_data = (totals[key] ||= [0, 0.0, 0.0, key])
128
+ total_data[0] += data[0]
129
+ total_data[1] += data[1]
130
+ total_data[2] += data[2]
131
+ end
132
+ end
133
+
134
+ # Maybe we should show a per thread output and a totals view?
135
+
136
+ data = totals.values
137
+ data = data.sort_by{|x| -x[2]}
138
+ sum = 0
139
+ f.printf " %% cumulative self self total\n"
140
+ f.printf " time seconds seconds calls ms/call ms/call name\n"
141
+ for d in data
142
+ sum += d[2]
143
+ f.printf "%6.2f %8.2f %8.2f %8d ", d[2]/total*100, sum, d[2], d[0]
144
+ f.printf "%8.2f %8.2f %s\n", d[2]*1000/d[0], d[1]*1000/d[0], d[3]
145
+ end
146
+ f.printf "%6.2f %8.2f %8.2f %8d ", 0.0, total, 0.0, 1 # ???
147
+ f.printf "%8.2f %8.2f %s\n", 0.0, total*1000, "#toplevel" # ???
148
+ end
149
+ end
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "profile/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "profile"
7
+ spec.version = Profile::VERSION
8
+ spec.authors = ["Yukihiro Matsumoto"]
9
+ spec.email = ["matz@ruby-lang.org"]
10
+
11
+ spec.summary = %q{Profile provides a way to Profile your Ruby application.}
12
+ spec.description = %q{Profile provides a way to Profile your Ruby application.}
13
+ spec.homepage = "https://github.com/ruby/profile"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/ruby/profile.git"
17
+
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 2.0"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: profile
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Yukihiro Matsumoto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Profile provides a way to Profile your Ruby application.
42
+ email:
43
+ - matz@ruby-lang.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - README.md
51
+ - Rakefile
52
+ - bin/console
53
+ - bin/setup
54
+ - lib/profile.rb
55
+ - lib/profile/version.rb
56
+ - lib/profiler.rb
57
+ - profile.gemspec
58
+ homepage: https://github.com/ruby/profile
59
+ licenses: []
60
+ metadata:
61
+ homepage_uri: https://github.com/ruby/profile
62
+ source_code_uri: https://github.com/ruby/profile.git
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.2.0.pre1
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Profile provides a way to Profile your Ruby application.
82
+ test_files: []