perftools.rb 0.1.8 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -114,11 +114,11 @@ google-perftools for ruby code
114
114
 
115
115
  To profile C code, download and build an unpatched perftools (libunwind or ./configure --enable-frame-pointers required on x86_64):
116
116
 
117
- wget http://google-perftools.googlecode.com/files/google-perftools-1.2.tar.gz
118
- tar zxvf google-perftools-1.2.tar.gz
119
- cd google-perftools-1.2
117
+ wget http://google-perftools.googlecode.com/files/google-perftools-1.3.tar.gz
118
+ tar zxvf google-perftools-1.3.tar.gz
119
+ cd google-perftools-1.3
120
120
 
121
- ./configure --prefix=/opt --disable-shared
121
+ ./configure --prefix=/opt
122
122
  make
123
123
  sudo make install
124
124
 
data/ext/extconf.rb CHANGED
@@ -36,6 +36,7 @@ Dir.chdir('src') do
36
36
  xsystem("tar zxvf #{perftools}")
37
37
  Dir.chdir(dir) do
38
38
  xsystem("patch -p1 < ../../../patches/perftools.patch")
39
+ xsystem("patch -p1 < ../../../patches/perftools-gc.patch")
39
40
  xsystem("patch -p1 < ../../../patches/perftools-osx.patch") if RUBY_PLATFORM =~ /darwin/
40
41
  xsystem("patch -p1 < ../../../patches/perftools-debug.patch")# if ENV['DEBUG']
41
42
  end
@@ -63,4 +64,4 @@ end
63
64
 
64
65
  $libs = append_library($libs, 'rubyprofiler')
65
66
  have_func('rb_during_gc', 'ruby.h')
66
- create_makefile 'perftools'
67
+ create_makefile 'perftools'
data/ext/perftools.c CHANGED
@@ -3,6 +3,7 @@
3
3
  #include <env.h>
4
4
 
5
5
  static VALUE Iallocate;
6
+ static VALUE I__send__;
6
7
 
7
8
  static inline void
8
9
  save_frame(struct FRAME *frame, void** result, int *depth)
@@ -12,6 +13,9 @@ save_frame(struct FRAME *frame, void** result, int *depth)
12
13
  // if (BUILTIN_TYPE(klass) == T_ICLASS)
13
14
  // klass = RBASIC(klass)->klass;
14
15
 
16
+ if (frame->last_func == I__send__)
17
+ return;
18
+
15
19
  if (FL_TEST(klass, FL_SINGLETON) &&
16
20
  (BUILTIN_TYPE(frame->self) == T_CLASS || BUILTIN_TYPE(frame->self) == T_MODULE))
17
21
  result[(*depth)++] = (void*) frame->self;
@@ -42,6 +46,8 @@ rb_stack_trace(void** result, int max_depth)
42
46
  }
43
47
  #endif
44
48
 
49
+ // XXX SIGPROF can come in while ruby_frame is in an inconsistent state (rb_call0), so we ignore the top-most frame
50
+ /*
45
51
  // XXX does it make sense to track allocations or not?
46
52
  if (frame->last_func == ID_ALLOCATOR) {
47
53
  frame = frame->prev;
@@ -50,6 +56,7 @@ rb_stack_trace(void** result, int max_depth)
50
56
  if (frame->last_func) {
51
57
  save_frame(frame, result, &depth);
52
58
  }
59
+ */
53
60
 
54
61
  for (; frame && (n = frame->node); frame = frame->prev) {
55
62
  if (frame->prev && frame->prev->last_func) {
@@ -70,6 +77,7 @@ rb_stack_trace(void** result, int max_depth)
70
77
  static VALUE cPerfTools;
71
78
  static VALUE cCpuProfiler;
72
79
  static VALUE bProfilerRunning;
80
+ static VALUE gc_hook;
73
81
 
74
82
  VALUE
75
83
  cpuprofiler_running_p(VALUE self)
@@ -108,6 +116,12 @@ cpuprofiler_start(VALUE self, VALUE filename)
108
116
  return Qtrue;
109
117
  }
110
118
 
119
+ static void
120
+ cpuprofiler_gc_mark()
121
+ {
122
+ ProfilerGcMark(rb_gc_mark);
123
+ }
124
+
111
125
  void
112
126
  Init_perftools()
113
127
  {
@@ -115,8 +129,12 @@ Init_perftools()
115
129
  cCpuProfiler = rb_define_class_under(cPerfTools, "CpuProfiler", rb_cObject);
116
130
  bProfilerRunning = Qfalse;
117
131
  Iallocate = rb_intern("allocate");
132
+ I__send__ = rb_intern("__send__");
118
133
 
119
134
  rb_define_singleton_method(cCpuProfiler, "running?", cpuprofiler_running_p, 0);
120
135
  rb_define_singleton_method(cCpuProfiler, "start", cpuprofiler_start, 1);
121
136
  rb_define_singleton_method(cCpuProfiler, "stop", cpuprofiler_stop, 0);
122
- }
137
+
138
+ gc_hook = Data_Wrap_Struct(cCpuProfiler, cpuprofiler_gc_mark, NULL, NULL);
139
+ rb_global_variable(&gc_hook);
140
+ }
@@ -0,0 +1,107 @@
1
+ diff --git a/src/profiledata.cc b/src/profiledata.cc
2
+ index e6240d9..b901ee8 100644
3
+ --- a/src/profiledata.cc
4
+ +++ b/src/profiledata.cc
5
+ @@ -198,6 +198,29 @@ static void DumpProcSelfMaps(int fd) {
6
+ }
7
+ }
8
+
9
+ +#ifdef BUILD_FOR_RUBY
10
+ +void ProfileData::GcMark(void (*mark)(VALUE)) {
11
+ + if (!enabled()) {
12
+ + return;
13
+ + }
14
+ +
15
+ + for (int b = 0; b < kBuckets; b++) {
16
+ + Bucket* bucket = &hash_[b];
17
+ + for (int a = 0; a < kAssociativity; a++) {
18
+ + if (bucket->entry[a].count > 0) {
19
+ + Entry e = bucket->entry[a];
20
+ + if (e.depth > 1)
21
+ + for (int n=0; n<e.depth; n+=3) {
22
+ + if (e.stack[n])
23
+ + mark(e.stack[n]);
24
+ + mark(e.stack[n+1]);
25
+ + }
26
+ + }
27
+ + }
28
+ + }
29
+ +}
30
+ +#endif
31
+ +
32
+ void ProfileData::Stop() {
33
+ if (!enabled()) {
34
+ return;
35
+ diff --git a/src/profiledata.h b/src/profiledata.h
36
+ index 67c463d..1df79c2 100644
37
+ --- a/src/profiledata.h
38
+ +++ b/src/profiledata.h
39
+ @@ -40,6 +40,12 @@
40
+ #ifndef BASE_PROFILEDATA_H_
41
+ #define BASE_PROFILEDATA_H_
42
+
43
+ +#ifdef BUILD_FOR_RUBY
44
+ +extern "C" {
45
+ + typedef unsigned long VALUE;
46
+ +}
47
+ +#endif
48
+ +
49
+ #include <config.h>
50
+ #include <time.h> // for time_t
51
+ #include <stdint.h>
52
+ @@ -141,6 +147,10 @@ class ProfileData {
53
+ // Get the current state of the data collector.
54
+ void GetCurrentState(State* state) const;
55
+
56
+ +#ifdef BUILD_FOR_RUBY
57
+ + void GcMark(void (*cb)(VALUE));
58
+ +#endif
59
+ +
60
+ private:
61
+ static const int kAssociativity = 4; // For hashtable
62
+ static const int kBuckets = 1 << 10; // For hashtable
63
+ diff --git a/src/profiler.cc b/src/profiler.cc
64
+ index 21c7669..b7277c7 100644
65
+ --- a/src/profiler.cc
66
+ +++ b/src/profiler.cc
67
+ @@ -87,6 +87,10 @@ class CpuProfiler {
68
+ // Write the data to disk (and continue profiling).
69
+ void FlushTable();
70
+
71
+ +#ifdef BUILD_FOR_RUBY
72
+ + void GcMark(void (*cb)(VALUE));
73
+ +#endif
74
+ +
75
+ bool Enabled();
76
+
77
+ void GetCurrentState(ProfilerState* state);
78
+ @@ -221,6 +225,16 @@ void CpuProfiler::FlushTable() {
79
+ EnableHandler();
80
+ }
81
+
82
+ +#ifdef BUILD_FOR_RUBY
83
+ +void CpuProfiler::GcMark(void (*cb)(VALUE)) {
84
+ + if (!collector_.enabled()) {
85
+ + return;
86
+ + }
87
+ +
88
+ + collector_.GcMark(cb);
89
+ +}
90
+ +#endif
91
+ +
92
+ bool CpuProfiler::Enabled() {
93
+ SpinLockHolder cl(&lock_);
94
+ return collector_.enabled();
95
+ @@ -300,6 +314,12 @@ extern "C" void ProfilerFlush() {
96
+ CpuProfiler::instance_.FlushTable();
97
+ }
98
+
99
+ +#ifdef BUILD_FOR_RUBY
100
+ +extern "C" void ProfilerGcMark(void (*cb)(VALUE)) {
101
+ + CpuProfiler::instance_.GcMark(cb);
102
+ +}
103
+ +#endif
104
+ +
105
+ extern "C" int ProfilingIsEnabledForAllThreads() {
106
+ return CpuProfiler::instance_.Enabled();
107
+ }
data/perftools.rb.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'perftools.rb'
3
- s.version = '0.1.8'
4
- s.date = '2009-06-15'
3
+ s.version = '0.2.5'
4
+ s.date = '2009-09-16'
5
5
  s.rubyforge_project = 'perftools-rb'
6
6
  s.summary = 'google-perftools for ruby code'
7
7
  s.description = 'A sampling profiler for ruby code based on patches to google-perftools'
@@ -23,6 +23,7 @@ spec = Gem::Specification.new do |s|
23
23
  "ext/extconf.rb",
24
24
  "ext/perftools.c",
25
25
  "patches/perftools-debug.patch",
26
+ "patches/perftools-gc.patch",
26
27
  "patches/perftools-osx.patch",
27
28
  "patches/perftools.patch",
28
29
  "perftools.rb.gemspec"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perftools.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-15 00:00:00 -07:00
12
+ date: 2009-09-16 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -27,6 +27,7 @@ files:
27
27
  - ext/extconf.rb
28
28
  - ext/perftools.c
29
29
  - patches/perftools-debug.patch
30
+ - patches/perftools-gc.patch
30
31
  - patches/perftools-osx.patch
31
32
  - patches/perftools.patch
32
33
  - perftools.rb.gemspec