jruby_gc_stats 0.1-java
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.
- data/README.txt +31 -0
- data/lib/jruby/gc_stats.rb +138 -0
- metadata +63 -0
data/README.txt
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
Title: jruby-gc-stats
|
2
|
+
|
3
|
+
Description:
|
4
|
+
|
5
|
+
This is a set of GC-monitoring methods for JRuby that mimic behavior of Ruby
|
6
|
+
Enterprise Edition's GC methods. In our case, these are all implemented in
|
7
|
+
Ruby, using the JVM's built-in monitoring and management APIs.
|
8
|
+
|
9
|
+
Example Usage:
|
10
|
+
|
11
|
+
require 'jruby/gc_stats'
|
12
|
+
|
13
|
+
require 'pp'
|
14
|
+
puts "Enabling stats..."
|
15
|
+
GC.enable_stats
|
16
|
+
puts "allocation size: #{GC.allocation_size}"
|
17
|
+
puts "Running loop..."
|
18
|
+
1_000.times {
|
19
|
+
ary = []
|
20
|
+
1_000.times {ary << 'foo' + 'bar'}
|
21
|
+
}
|
22
|
+
puts "collections: #{GC.collections}"
|
23
|
+
puts "time: #{GC.time}ms"
|
24
|
+
puts "bytes since last GC: #{GC.growth}"
|
25
|
+
puts "size change: #{GC.allocation_size}"
|
26
|
+
puts "Dumping..."
|
27
|
+
GC.dump
|
28
|
+
|
29
|
+
puts "Dumping caller for all threads..."
|
30
|
+
2.times {Thread.new {sleep}}
|
31
|
+
pp caller_for_all_threads
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'jruby'
|
3
|
+
|
4
|
+
module GC
|
5
|
+
import java.lang.management.ManagementFactory
|
6
|
+
import java.lang.management.MemoryType
|
7
|
+
GC_MBEANS = ManagementFactory.garbage_collector_mxbeans
|
8
|
+
POOL_MBEANS = ManagementFactory.memory_pool_mxbeans
|
9
|
+
|
10
|
+
# no perf penalty for stats on JVM, but save current counts
|
11
|
+
def self.enable_stats
|
12
|
+
@enabled = true
|
13
|
+
@start_count = _collection_count
|
14
|
+
@start_time = _collection_time
|
15
|
+
@start_size = _total_pool_size
|
16
|
+
end
|
17
|
+
def self.disable_stats
|
18
|
+
@enabled = false
|
19
|
+
end
|
20
|
+
|
21
|
+
# Number of GC runs since stat collection started.
|
22
|
+
# This is accumulated across all GCs in the system.
|
23
|
+
def self.collections
|
24
|
+
raise "GC stats are not enabled" unless @enabled
|
25
|
+
new_count = _collection_count
|
26
|
+
new_count - @start_count
|
27
|
+
end
|
28
|
+
|
29
|
+
# Amount of time spent in GC since stat collection started
|
30
|
+
# This is accumulated across all GCs in the system.
|
31
|
+
def self.time
|
32
|
+
raise "GC stats are not enabled" unless @enabled
|
33
|
+
new_time = _collection_time
|
34
|
+
new_time - @start_time
|
35
|
+
end
|
36
|
+
|
37
|
+
# Number of heap bytes requested since the last GC run.
|
38
|
+
# This includes all memory pools.
|
39
|
+
def self.growth
|
40
|
+
_usage_versus_collected
|
41
|
+
end
|
42
|
+
|
43
|
+
# Dumping the basic data for each pool
|
44
|
+
def self.dump
|
45
|
+
filename = ENV['RUBY_GC_DATA_FILE']
|
46
|
+
begin
|
47
|
+
file = filename ? File.open(filename, 'w') : $stderr
|
48
|
+
for pool_bean in POOL_MBEANS
|
49
|
+
file.puts "Name: #{pool_bean.name}"
|
50
|
+
file.puts " Type: #{pool_bean.type}"
|
51
|
+
file.puts " Peak usage: #{pool_bean.peak_usage}"
|
52
|
+
file.puts " Current usage: #{pool_bean.usage}"
|
53
|
+
file.puts " Usage after last collection: #{pool_bean.collection_usage}"
|
54
|
+
file.puts " Managers: #{pool_bean.memory_manager_names.to_a.join(', ')}"
|
55
|
+
end
|
56
|
+
ensure
|
57
|
+
file.close if filename
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# A delta in the committed (active main memory) size of all memory pools
|
62
|
+
def self.allocation_size
|
63
|
+
new_size = _total_pool_size
|
64
|
+
new_size - @start_size
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.num_allocations
|
68
|
+
# not sure this can be tracked on JVM; allocations happen all over
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def self._collection_count
|
74
|
+
GC_MBEANS.inject(0) {|tot, bean| tot + bean.collection_count}
|
75
|
+
end
|
76
|
+
|
77
|
+
def self._collection_time
|
78
|
+
GC_MBEANS.inject(0) {|tot, bean| tot + bean.collection_time}
|
79
|
+
end
|
80
|
+
|
81
|
+
def self._usage_versus_collected
|
82
|
+
POOL_MBEANS.inject(0) do |tot, bean|
|
83
|
+
next tot if bean.type == MemoryType::NON_HEAP
|
84
|
+
tot + (bean.usage.used - bean.collection_usage.used)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def self._total_pool_size
|
89
|
+
POOL_MBEANS.inject(0) do |tot, bean|
|
90
|
+
tot + bean.usage.committed
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module ObjectSpace
|
96
|
+
def self.live_objects
|
97
|
+
# not sure if there's a way to get this without tooling API on JVM
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.allocated_objects
|
101
|
+
# ditto
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Object
|
106
|
+
def caller_for_all_threads
|
107
|
+
backtraces = {}
|
108
|
+
ts = JRuby.runtime.thread_service
|
109
|
+
ts.active_ruby_threads.each do |rthread|
|
110
|
+
tc = ts.get_thread_context_for_thread(rthread)
|
111
|
+
caller = tc.create_caller_backtrace(JRuby.runtime, 0)
|
112
|
+
backtraces[rthread] = caller
|
113
|
+
end
|
114
|
+
backtraces
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
if $0 == __FILE__
|
119
|
+
require 'pp'
|
120
|
+
puts "Enabling stats..."
|
121
|
+
GC.enable_stats
|
122
|
+
puts "allocation size: #{GC.allocation_size}"
|
123
|
+
puts "Running loop..."
|
124
|
+
1_000.times {
|
125
|
+
ary = []
|
126
|
+
1_000.times {ary << 'foo' + 'bar'}
|
127
|
+
}
|
128
|
+
puts "collections: #{GC.collections}"
|
129
|
+
puts "time: #{GC.time}ms"
|
130
|
+
puts "bytes since last GC: #{GC.growth}"
|
131
|
+
puts "size change: #{GC.allocation_size}"
|
132
|
+
puts "Dumping..."
|
133
|
+
GC.dump
|
134
|
+
|
135
|
+
puts "Dumping caller for all threads..."
|
136
|
+
2.times {Thread.new {sleep}}
|
137
|
+
pp caller_for_all_threads
|
138
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jruby_gc_stats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
version: "0.1"
|
9
|
+
platform: java
|
10
|
+
authors:
|
11
|
+
- Charles Oliver Nutter
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2010-04-24 19:01:44.476000 -05:00
|
17
|
+
default_executable:
|
18
|
+
dependencies: []
|
19
|
+
|
20
|
+
description: A set of GC-monitoring methods for JRuby similar to those in Ruby Enterprise Edition
|
21
|
+
email:
|
22
|
+
- headius@headius.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- README.txt
|
29
|
+
files:
|
30
|
+
- lib/jruby/gc_stats.rb
|
31
|
+
- README.txt
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/headius/jruby_gc_stats
|
34
|
+
licenses: []
|
35
|
+
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.3.6
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: A set of GC-monitoring methods for JRuby similar to those in Ruby Enterprise Edition
|
62
|
+
test_files: []
|
63
|
+
|