profile 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []