perftools.rb 0.2.5 → 0.3.1

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 CHANGED
@@ -134,7 +134,6 @@ google-perftools for ruby code
134
134
  * Add support for heap profiling to find memory leaks (PerfTools::HeapProfiler)
135
135
  * Allow both C and Ruby profiling
136
136
  * Add setter for the sampling interval
137
- * Add support for ruby 1.9
138
137
 
139
138
 
140
139
  === Resources
@@ -1,67 +1,93 @@
1
- require 'mkmf'
1
+ CWD = File.expand_path(File.dirname(__FILE__))
2
2
 
3
- if have_func('rb_thread_blocking_region')
4
- raise 'Ruby 1.9 is not supported yet'
3
+ def sys(cmd)
4
+ puts " -- #{cmd}"
5
+ unless ret = xsystem(cmd)
6
+ raise "#{cmd} failed, please report to perftools@tmm1.net with pastie.org link to #{CWD}/mkmf.log and #{CWD}/src/google-perftools-1.4/config.log"
7
+ end
8
+ ret
5
9
  end
6
10
 
11
+ require 'mkmf'
7
12
  require 'fileutils'
8
- require 'net/http'
9
13
 
10
- url = 'http://google-perftools.googlecode.com/files/google-perftools-1.3.tar.gz'
11
- perftools = File.basename(url)
12
- dir = File.basename(perftools, '.tar.gz')
13
-
14
- Logging.message "(I'm about to download and compile google-perftools.. this will definitely take a while)"
14
+ if RUBY_VERSION >= "1.9"
15
+ begin
16
+ require "ruby_core_source"
17
+ rescue LoadError
18
+ STDERR.puts "\n\n"
19
+ STDERR.puts "***************************************************************************************"
20
+ STDERR.puts "******************** PLEASE RUN gem install ruby_core_source FIRST ********************"
21
+ STDERR.puts "***************************************************************************************"
22
+ exit(1)
23
+ end
24
+ end
15
25
 
16
- FileUtils.mkdir_p('src')
26
+ perftools = File.basename('google-perftools-1.4.tar.gz')
27
+ dir = File.basename(perftools, '.tar.gz')
17
28
 
18
- if proxy = URI(ENV['http_proxy'] || ENV['HTTP_PROXY']) rescue nil
19
- proxy_host = proxy.host
20
- proxy_port = proxy.port
21
- proxy_user, proxy_pass = proxy.userinfo.split(/:/) if proxy.userinfo
22
- end
29
+ puts "(I'm about to compile google-perftools.. this will definitely take a while)"
23
30
 
24
31
  Dir.chdir('src') do
25
- unless File.exists?(perftools)
26
- Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass).get_response(URI(url)) do |res|
27
- File.open(perftools, 'wb') do |out|
28
- res.read_body do |chunk|
29
- out.write(chunk)
30
- end
31
- end
32
- end
33
- end
32
+ FileUtils.rm_rf(dir) if File.exists?(dir)
34
33
 
35
- unless File.exists?(dir)
36
- xsystem("tar zxvf #{perftools}")
37
- Dir.chdir(dir) do
38
- xsystem("patch -p1 < ../../../patches/perftools.patch")
39
- xsystem("patch -p1 < ../../../patches/perftools-gc.patch")
40
- xsystem("patch -p1 < ../../../patches/perftools-osx.patch") if RUBY_PLATFORM =~ /darwin/
41
- xsystem("patch -p1 < ../../../patches/perftools-debug.patch")# if ENV['DEBUG']
42
- end
34
+ sys("tar zxvf #{perftools}")
35
+ Dir.chdir(dir) do
36
+ sys("patch -p1 < ../../../patches/perftools.patch")
37
+ sys("patch -p1 < ../../../patches/perftools-pprof.patch")
38
+ sys("patch -p1 < ../../../patches/perftools-gc.patch")
39
+ sys("patch -p1 < ../../../patches/perftools-osx.patch") if RUBY_PLATFORM =~ /darwin/
40
+ sys("patch -p1 < ../../../patches/perftools-osx-106.patch") if RUBY_PLATFORM =~ /darwin10/
41
+ sys("patch -p1 < ../../../patches/perftools-debug.patch")
43
42
  end
44
43
 
45
- unless File.exists?('../bin/pprof')
46
- Dir.chdir(dir) do
47
- FileUtils.cp 'src/pprof', '../../../bin/'
48
- end
44
+ Dir.chdir(dir) do
45
+ FileUtils.cp 'src/pprof', '../../../bin/'
46
+ FileUtils.chmod 0755, '../../../bin/pprof'
49
47
  end
50
48
 
51
- unless File.exists?('../librubyprofiler.a')
52
- Dir.chdir(dir) do
53
- xsystem("./configure --disable-heap-profiler --disable-heap-checker --disable-shared")
54
- xsystem("make")
55
- FileUtils.cp '.libs/libprofiler.a', '../../librubyprofiler.a'
49
+ Dir.chdir(dir) do
50
+ if RUBY_PLATFORM =~ /darwin10/
51
+ ENV['CFLAGS'] = ENV['CXXFLAGS'] = '-D_XOPEN_SOURCE'
56
52
  end
53
+ sys("./configure --disable-heap-profiler --disable-heap-checker --disable-shared")
54
+ sys("make")
55
+ FileUtils.cp '.libs/libprofiler.a', '../../librubyprofiler.a'
57
56
  end
58
57
  end
59
58
 
59
+ $LIBPATH << CWD
60
+ $libs = append_library($libs, 'rubyprofiler')
61
+ def add_define(name)
62
+ $defs.push("-D#{name}")
63
+ end
64
+
60
65
  case RUBY_PLATFORM
61
66
  when /darwin/, /linux/
62
67
  CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
63
68
  end
64
69
 
65
- $libs = append_library($libs, 'rubyprofiler')
66
- have_func('rb_during_gc', 'ruby.h')
67
- create_makefile 'perftools'
70
+ if RUBY_VERSION >= "1.9"
71
+ add_define 'RUBY19'
72
+
73
+ hdrs = proc {
74
+ have_header("vm_core.h") and
75
+ have_header("iseq.h") and
76
+ have_header("insns.inc") and
77
+ have_header("insns_info.inc")
78
+ }
79
+ have_func('rb_during_gc', 'ruby.h')
80
+
81
+ unless Ruby_core_source::create_makefile_with_core(hdrs, "perftools")
82
+ STDERR.puts "\n\n"
83
+ STDERR.puts "***************************************************************************************"
84
+ STDERR.puts "********************** Ruby_core_source::create_makefile FAILED ***********************"
85
+ STDERR.puts "***************************************************************************************"
86
+ exit(1)
87
+ end
88
+ else
89
+ add_define 'RUBY18'
90
+
91
+ have_func('rb_during_gc', 'ruby.h')
92
+ create_makefile 'perftools'
93
+ end
@@ -1,78 +1,160 @@
1
1
  #include <ruby.h>
2
- #include <node.h>
3
- #include <env.h>
4
-
5
2
  static VALUE Iallocate;
6
3
  static VALUE I__send__;
7
4
 
8
- static inline void
9
- save_frame(struct FRAME *frame, void** result, int *depth)
10
- {
11
- VALUE klass = frame->last_class;
12
- // XXX what is an ICLASS anyway?
13
- // if (BUILTIN_TYPE(klass) == T_ICLASS)
14
- // klass = RBASIC(klass)->klass;
15
-
16
- if (frame->last_func == I__send__)
17
- return;
18
-
19
- if (FL_TEST(klass, FL_SINGLETON) &&
20
- (BUILTIN_TYPE(frame->self) == T_CLASS || BUILTIN_TYPE(frame->self) == T_MODULE))
21
- result[(*depth)++] = (void*) frame->self;
22
- else
23
- result[(*depth)++] = 0;
24
-
25
- result[(*depth)++] = (void*) klass;
26
- result[(*depth)++] = (void*) (frame->last_func == ID_ALLOCATOR ? Iallocate : frame->last_func);
27
- }
5
+ #define SAVE_FRAME() \
6
+ if (method != I__send__) { \
7
+ if (FL_TEST(klass, FL_SINGLETON) && (BUILTIN_TYPE(self) == T_CLASS || BUILTIN_TYPE(self) == T_MODULE)) \
8
+ result[depth++] = (void*) self; \
9
+ else \
10
+ result[depth++] = 0; \
11
+ \
12
+ result[depth++] = (void*) klass; \
13
+ result[depth++] = (void*) (method == ID_ALLOCATOR ? Iallocate : method); \
14
+ }
28
15
 
29
- int
30
- rb_stack_trace(void** result, int max_depth)
31
- {
32
- int depth = 0;
33
- struct FRAME *frame = ruby_frame;
34
- NODE *n;
16
+ #ifdef RUBY18
17
+ #include <node.h>
18
+ #include <env.h>
19
+
20
+ int
21
+ rb_stack_trace(void** result, int max_depth)
22
+ {
23
+ struct FRAME *frame = ruby_frame;
24
+ NODE *n;
25
+
26
+ VALUE klass, self;
27
+ ID method;
28
+ int depth = 0;
29
+
30
+ if (max_depth == 0)
31
+ return 0;
35
32
 
36
- if (max_depth == 0)
37
- return 0;
33
+ #ifdef HAVE_RB_DURING_GC
34
+ if (rb_during_gc()) {
35
+ result[0] = rb_gc;
36
+ return 1;
37
+ }
38
+ #endif
39
+
40
+ /*
41
+ // XXX does it make sense to track allocations or not?
42
+ if (frame->last_func == ID_ALLOCATOR) {
43
+ frame = frame->prev;
44
+ }
45
+
46
+ // XXX SIGPROF can come in while ruby_frame is in an inconsistent state (rb_call0), so we ignore the top-most frame
47
+ if (frame->last_func) {
48
+ self = frame->self;
49
+ klass = frame->last_class;
50
+ method = frame->last_func;
51
+ SAVE_FRAME();
52
+ }
53
+ */
54
+
55
+ for (; frame && (n = frame->node); frame = frame->prev) {
56
+ if (frame->prev && frame->prev->last_func) {
57
+ if (frame->prev->node == n) {
58
+ if (frame->prev->last_func == frame->last_func) continue;
59
+ }
38
60
 
39
- // XXX: figure out what these mean. is there a way to access them from an extension?
40
- // if (rb_prohibit_interrupt || !rb_trap_immediate) return 0;
61
+ if (depth+3 > max_depth)
62
+ break;
63
+
64
+ self = frame->prev->self;
65
+ klass = frame->prev->last_class;
66
+ method = frame->prev->last_func;
67
+ SAVE_FRAME();
68
+ }
69
+ }
41
70
 
42
- #ifdef HAVE_RB_DURING_GC
43
- if (rb_during_gc()) {
44
- result[0] = rb_gc;
45
- return 1;
71
+ return depth;
46
72
  }
47
73
  #endif
48
74
 
49
- // XXX SIGPROF can come in while ruby_frame is in an inconsistent state (rb_call0), so we ignore the top-most frame
50
- /*
51
- // XXX does it make sense to track allocations or not?
52
- if (frame->last_func == ID_ALLOCATOR) {
53
- frame = frame->prev;
54
- }
75
+ #ifdef RUBY19
76
+ #include <vm_core.h>
77
+ #include <iseq.h>
55
78
 
56
- if (frame->last_func) {
57
- save_frame(frame, result, &depth);
58
- }
59
- */
79
+ int
80
+ rb_stack_trace(void** result, int max_depth)
81
+ {
82
+ rb_thread_t *th = GET_THREAD();
83
+ rb_control_frame_t *cfp = th->cfp;
84
+ rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
85
+
86
+ VALUE klass, self;
87
+ ID method;
88
+ int depth = 0;
89
+
90
+ if (max_depth == 0)
91
+ return 0;
92
+
93
+ #ifdef HAVE_RB_DURING_GC
94
+ if (rb_during_gc()) {
95
+ result[0] = rb_gc;
96
+ return 1;
97
+ }
98
+ #endif
99
+
100
+ while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp) && depth+3 < max_depth) {
101
+ rb_iseq_t *iseq = cfp->iseq;
60
102
 
61
- for (; frame && (n = frame->node); frame = frame->prev) {
62
- if (frame->prev && frame->prev->last_func) {
63
- if (frame->prev->node == n) {
64
- if (frame->prev->last_func == frame->last_func) continue;
103
+ if (iseq && iseq->type == ISEQ_TYPE_METHOD) {
104
+ self = iseq->self;
105
+ klass = iseq->klass;
106
+ method = iseq->defined_method_id;
107
+ SAVE_FRAME();
65
108
  }
66
109
 
67
- if (depth+3 > max_depth)
68
- break;
110
+ switch(VM_FRAME_TYPE(cfp)) {
111
+ case VM_FRAME_MAGIC_METHOD:
112
+ case VM_FRAME_MAGIC_CFUNC:
113
+ self = cfp->self;
114
+ klass = cfp->method_class;
115
+ method = cfp->method_id;
116
+ SAVE_FRAME();
117
+ break;
118
+ }
69
119
 
70
- save_frame(frame->prev, result, &depth);
120
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
71
121
  }
122
+
123
+ return depth;
72
124
  }
73
125
 
74
- return depth;
75
- }
126
+ #if 0
127
+ void
128
+ rb_dump_stack()
129
+ {
130
+ rb_thread_t *th = GET_THREAD();
131
+ rb_control_frame_t *cfp = th->cfp;
132
+ rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
133
+ ID func;
134
+
135
+ printf("\n\n*********************\n");
136
+ while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
137
+ printf("cfp (%p):\n", cfp);
138
+ printf(" type: 0x%x\n", VM_FRAME_TYPE(cfp));
139
+ printf(" pc: %p\n", cfp->pc);
140
+ printf(" iseq: %p\n", cfp->iseq);
141
+ if (cfp->iseq) {
142
+ printf(" type: %d\n", FIX2INT(cfp->iseq->type));
143
+ printf(" self: %p\n", cfp->iseq->self);
144
+ printf(" klass: %p (%s)\n", cfp->iseq->klass, cfp->iseq->klass ? rb_class2name(cfp->iseq->klass) : "");
145
+ printf(" method: %p (%s)\n", cfp->iseq->defined_method_id, cfp->iseq->defined_method_id ? rb_id2name(cfp->iseq->defined_method_id) : "");
146
+ }
147
+ printf(" self: %p\n", cfp->self);
148
+ printf(" klass: %p (%s)\n", cfp->method_class, cfp->method_class ? rb_class2name(cfp->method_class) : "");
149
+ printf(" method: %p (%s)\n", cfp->method_id, cfp->method_id ? rb_id2name(cfp->method_id) : "");
150
+
151
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
152
+ printf("\n");
153
+ }
154
+ printf("*********************\n\n");
155
+ }
156
+ #endif
157
+ #endif
76
158
 
77
159
  static VALUE cPerfTools;
78
160
  static VALUE cCpuProfiler;
@@ -1,8 +1,8 @@
1
1
  diff --git a/Makefile.in b/Makefile.in
2
- index a7a4fb5..bfa0347 100644
2
+ index c3bf409..c613939 100644
3
3
  --- a/Makefile.in
4
4
  +++ b/Makefile.in
5
- @@ -1067,13 +1067,13 @@ AUTOMAKE = @AUTOMAKE@
5
+ @@ -1367,13 +1367,13 @@ AUTOMAKE = @AUTOMAKE@
6
6
  AWK = @AWK@
7
7
  CC = @CC@
8
8
  CCDEPMODE = @CCDEPMODE@
@@ -33,7 +33,7 @@ index e6240d9..b901ee8 100644
33
33
  if (!enabled()) {
34
34
  return;
35
35
  diff --git a/src/profiledata.h b/src/profiledata.h
36
- index 67c463d..1df79c2 100644
36
+ index 67c463d..a68e12f 100644
37
37
  --- a/src/profiledata.h
38
38
  +++ b/src/profiledata.h
39
39
  @@ -40,6 +40,12 @@
@@ -54,14 +54,14 @@ index 67c463d..1df79c2 100644
54
54
  void GetCurrentState(State* state) const;
55
55
 
56
56
  +#ifdef BUILD_FOR_RUBY
57
- + void GcMark(void (*cb)(VALUE));
57
+ + void GcMark(void (*cb)(VALUE));
58
58
  +#endif
59
59
  +
60
60
  private:
61
61
  static const int kAssociativity = 4; // For hashtable
62
62
  static const int kBuckets = 1 << 10; // For hashtable
63
63
  diff --git a/src/profiler.cc b/src/profiler.cc
64
- index 21c7669..b7277c7 100644
64
+ index d89a53a..37234b2 100644
65
65
  --- a/src/profiler.cc
66
66
  +++ b/src/profiler.cc
67
67
  @@ -87,6 +87,10 @@ class CpuProfiler {
@@ -69,7 +69,7 @@ index 21c7669..b7277c7 100644
69
69
  void FlushTable();
70
70
 
71
71
  +#ifdef BUILD_FOR_RUBY
72
- + void GcMark(void (*cb)(VALUE));
72
+ + void GcMark(void (*cb)(VALUE));
73
73
  +#endif
74
74
  +
75
75
  bool Enabled();
@@ -81,27 +81,27 @@ index 21c7669..b7277c7 100644
81
81
 
82
82
  +#ifdef BUILD_FOR_RUBY
83
83
  +void CpuProfiler::GcMark(void (*cb)(VALUE)) {
84
- + if (!collector_.enabled()) {
85
- + return;
86
- + }
84
+ + if (!collector_.enabled()) {
85
+ + return;
86
+ + }
87
87
  +
88
- + collector_.GcMark(cb);
88
+ + collector_.GcMark(cb);
89
89
  +}
90
90
  +#endif
91
91
  +
92
92
  bool CpuProfiler::Enabled() {
93
93
  SpinLockHolder cl(&lock_);
94
94
  return collector_.enabled();
95
- @@ -300,6 +314,12 @@ extern "C" void ProfilerFlush() {
95
+ @@ -300,6 +314,12 @@ extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() {
96
96
  CpuProfiler::instance_.FlushTable();
97
97
  }
98
98
 
99
99
  +#ifdef BUILD_FOR_RUBY
100
- +extern "C" void ProfilerGcMark(void (*cb)(VALUE)) {
100
+ +extern "C" PERFTOOLS_DLL_DECL void ProfilerGcMark(void (*cb)(VALUE)) {
101
101
  + CpuProfiler::instance_.GcMark(cb);
102
102
  +}
103
103
  +#endif
104
104
  +
105
- extern "C" int ProfilingIsEnabledForAllThreads() {
105
+ extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() {
106
106
  return CpuProfiler::instance_.Enabled();
107
107
  }
@@ -0,0 +1,96 @@
1
+ diff --git a/Makefile.in b/Makefile.in
2
+ index c613939..1a901d5 100644
3
+ --- a/Makefile.in
4
+ diff --git a/src/base/sysinfo.cc b/src/base/sysinfo.cc
5
+ index a2bc2a9..10b8886 100644
6
+ --- a/src/base/sysinfo.cc
7
+ +++ b/src/base/sysinfo.cc
8
+ @@ -728,26 +728,59 @@ bool ProcMapsIterator::NextExt(uint64 *start, uint64 *end, char **flags,
9
+
10
+ // We start with the next load command (we've already looked at this one).
11
+ for (current_load_cmd_--; current_load_cmd_ >= 0; current_load_cmd_--) {
12
+ - const char* lc = ((const char *)hdr + sizeof(struct mach_header));
13
+ + const char* lc;
14
+ + uint32_t seg_marker;
15
+ + #if defined(MH_MAGIC_64)
16
+ + if (hdr->magic == MH_MAGIC_64) {
17
+ + lc = ((const char *)hdr + sizeof(struct mach_header_64));
18
+ + seg_marker = LC_SEGMENT_64;
19
+ + } else {
20
+ + #endif
21
+ + lc = ((const char *)hdr + sizeof(struct mach_header));
22
+ + seg_marker = LC_SEGMENT;
23
+ + #if defined(MH_MAGIC_64)
24
+ + }
25
+ + #endif
26
+ // TODO(csilvers): make this not-quadradic (increment and hold state)
27
+ for (int j = 0; j < current_load_cmd_; j++) // advance to *our* load_cmd
28
+ lc += ((const load_command *)lc)->cmdsize;
29
+ - if (((const load_command *)lc)->cmd == LC_SEGMENT) {
30
+ + if (((const load_command *)lc)->cmd == seg_marker) {
31
+ const intptr_t dlloff = _dyld_get_image_vmaddr_slide(current_image_);
32
+ - const segment_command* sc = (const segment_command *)lc;
33
+ - if (start) *start = sc->vmaddr + dlloff;
34
+ - if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
35
+ - if (flags) *flags = kDefaultPerms; // can we do better?
36
+ - if (offset) *offset = sc->fileoff;
37
+ - if (inode) *inode = 0;
38
+ - if (filename)
39
+ - *filename = const_cast<char*>(_dyld_get_image_name(current_image_));
40
+ - if (file_mapping) *file_mapping = 0;
41
+ - if (file_pages) *file_pages = 0; // could we use sc->filesize?
42
+ - if (anon_mapping) *anon_mapping = 0;
43
+ - if (anon_pages) *anon_pages = 0;
44
+ - if (dev) *dev = 0;
45
+ - return true;
46
+ + #if defined(MH_MAGIC_64)
47
+ + if (hdr->magic == MH_MAGIC_64) {
48
+ + const segment_command_64* sc = (const segment_command_64 *)lc;
49
+ + if (start) *start = sc->vmaddr + dlloff;
50
+ + if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
51
+ + if (flags) *flags = kDefaultPerms; // can we do better?
52
+ + if (offset) *offset = sc->fileoff;
53
+ + if (inode) *inode = 0;
54
+ + if (filename)
55
+ + *filename = const_cast<char*>(_dyld_get_image_name(current_image_));
56
+ + if (file_mapping) *file_mapping = 0;
57
+ + if (file_pages) *file_pages = 0; // could we use sc->filesize?
58
+ + if (anon_mapping) *anon_mapping = 0;
59
+ + if (anon_pages) *anon_pages = 0;
60
+ + if (dev) *dev = 0;
61
+ + return true;
62
+ + } else {
63
+ + #endif
64
+ + const segment_command* sc = (const segment_command *)lc;
65
+ + if (start) *start = sc->vmaddr + dlloff;
66
+ + if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
67
+ + if (flags) *flags = kDefaultPerms; // can we do better?
68
+ + if (offset) *offset = sc->fileoff;
69
+ + if (inode) *inode = 0;
70
+ + if (filename)
71
+ + *filename = const_cast<char*>(_dyld_get_image_name(current_image_));
72
+ + if (file_mapping) *file_mapping = 0;
73
+ + if (file_pages) *file_pages = 0; // could we use sc->filesize?
74
+ + if (anon_mapping) *anon_mapping = 0;
75
+ + if (anon_pages) *anon_pages = 0;
76
+ + if (dev) *dev = 0;
77
+ + return true;
78
+ + #if defined(MH_MAGIC_64)
79
+ + }
80
+ + #endif
81
+ }
82
+ }
83
+ // If we get here, no more load_cmd's in this image talk about
84
+ diff --git a/src/pprof b/src/pprof
85
+ index 3531300..b256ed2 100755
86
+ --- a/src/pprof
87
+ +++ b/src/pprof
88
+ @@ -3193,7 +3193,7 @@ sub ParseTextSectionHeaderFromOtool {
89
+ $sectname = $1;
90
+ } elsif ($line =~ /segname (\w+)/) {
91
+ $segname = $1;
92
+ - } elsif (!($cmd eq "LC_SEGMENT" &&
93
+ + } elsif (!(($cmd eq "LC_SEGMENT" || $cmd eq "LC_SEGMENT_64") &&
94
+ $sectname eq "__text" &&
95
+ $segname eq "__TEXT")) {
96
+ next;
@@ -1,8 +1,8 @@
1
1
  diff --git a/Makefile.in b/Makefile.in
2
- index e3690b2..a7a4fb5 100644
2
+ index 566d77c..c3bf409 100644
3
3
  --- a/Makefile.in
4
4
  +++ b/Makefile.in
5
- @@ -1097,7 +1097,7 @@ INSTALL_DATA = @INSTALL_DATA@
5
+ @@ -1397,7 +1397,7 @@ INSTALL_DATA = @INSTALL_DATA@
6
6
  INSTALL_PROGRAM = @INSTALL_PROGRAM@
7
7
  INSTALL_SCRIPT = @INSTALL_SCRIPT@
8
8
  INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
@@ -0,0 +1,56 @@
1
+ diff --git a/src/pprof b/src/pprof
2
+ index b5ef29a..25b956d 100755
3
+ --- a/src/pprof
4
+ +++ b/src/pprof
5
+ @@ -530,7 +530,8 @@ sub Main() {
6
+ my $symbol_map = {};
7
+
8
+ # Read one profile, pick the last item on the list
9
+ - my $data = ReadProfile($main::prog, pop(@main::profile_files));
10
+ + my $fname = pop(@main::profile_files);
11
+ + my $data = ReadProfile($main::prog, $fname);
12
+ my $profile = $data->{profile};
13
+ my $pcs = $data->{pcs};
14
+ my $libs = $data->{libs}; # Info about main program and shared libraries
15
+ @@ -567,6 +568,17 @@ sub Main() {
16
+ $symbols = ExtractSymbols($libs, $pcs);
17
+ }
18
+
19
+ + if (-e "$fname.symbols") {
20
+ + open(SYMBOLS, "<$fname.symbols");
21
+ + while(<SYMBOLS>){
22
+ + chop;
23
+ + if (m/(.+?)\s*:\s*(.*)/){
24
+ + $symbols->{$1}[0] = $2;
25
+ + }
26
+ + }
27
+ + close(SYMBOLS);
28
+ + }
29
+ +
30
+ # Remove uniniteresting stack items
31
+ $profile = RemoveUninterestingFrames($symbols, $profile);
32
+
33
+ @@ -1927,6 +1927,7 @@ sub RemoveUninterestingFrames {
34
+ 'ProfileData::prof_handler', # historical
35
+ 'CpuProfiler::prof_handler',
36
+ '__FRAME_END__',
37
+ + 'PerfTools::CpuProfiler.start',
38
+ '__pthread_sighandler',
39
+ '__restore') {
40
+ $skip{$name} = 1;
41
+ @@ -1935,6 +1936,7 @@ sub RemoveUninterestingFrames {
42
+ # Nothing skipped for unknown types
43
+ }
44
+
45
+ +=pod
46
+ if ($main::profile_type eq 'cpu') {
47
+ # If all the second-youngest program counters are the same,
48
+ # this STRONGLY suggests that it is an artifact of measurement,
49
+ @@ -1959,6 +1961,7 @@ sub RemoveUninterestingFrames {
50
+ $profile = $result;
51
+ }
52
+ }
53
+ +=cut
54
+
55
+ my $result = {};
56
+ foreach my $k (keys(%{$profile})) {
@@ -1,8 +1,8 @@
1
1
  diff --git a/Makefile.in b/Makefile.in
2
- index 8ba85fb..e3690b2 100644
2
+ index 232d2ec..566d77c 100644
3
3
  --- a/Makefile.in
4
4
  +++ b/Makefile.in
5
- @@ -1067,13 +1067,13 @@ AUTOMAKE = @AUTOMAKE@
5
+ @@ -1367,13 +1367,13 @@ AUTOMAKE = @AUTOMAKE@
6
6
  AWK = @AWK@
7
7
  CC = @CC@
8
8
  CCDEPMODE = @CCDEPMODE@
@@ -18,38 +18,6 @@ index 8ba85fb..e3690b2 100644
18
18
  CYGPATH_W = @CYGPATH_W@
19
19
  DEFS = @DEFS@
20
20
  DEPDIR = @DEPDIR@
21
- diff --git a/src/pprof b/src/pprof
22
- index 9d4d0e8..a41fcb1 100755
23
- --- a/src/pprof
24
- +++ b/src/pprof
25
- @@ -504,7 +504,8 @@ sub Main() {
26
- FetchDynamicProfiles();
27
-
28
- # Read one profile, pick the last item on the list
29
- - my $data = ReadProfile($main::prog, pop(@main::profile_files));
30
- + my $fname = pop(@main::profile_files);
31
- + my $data = ReadProfile($main::prog, $fname);
32
- my $profile = $data->{profile};
33
- my $pcs = $data->{pcs};
34
- my $libs = $data->{libs}; # Info about main program and shared libraries
35
- @@ -549,6 +550,17 @@ sub Main() {
36
- $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore);
37
- }
38
-
39
- + if (-e "$fname.symbols") {
40
- + open(SYMBOLS, "<$fname.symbols");
41
- + while(<SYMBOLS>){
42
- + chop;
43
- + if (m/(.+?)\s*:\s*(.*)/){
44
- + $symbols->{$1}[0] = $2;
45
- + }
46
- + }
47
- + close(SYMBOLS);
48
- + }
49
- +
50
- my $calls = ExtractCalls($symbols, $profile);
51
-
52
- # Reduce profiles to required output granularity, and also clean
53
21
  diff --git a/src/profile-handler.cc b/src/profile-handler.cc
54
22
  index e658d30..370d012 100644
55
23
  --- a/src/profile-handler.cc
@@ -227,7 +195,7 @@ index da7ea9e..67c463d 100644
227
195
 
228
196
  // Move 'entry' to the eviction buffer.
229
197
  diff --git a/src/profiler.cc b/src/profiler.cc
230
- index c51c7b2..21c7669 100644
198
+ index 183a7c7..d89a53a 100644
231
199
  --- a/src/profiler.cc
232
200
  +++ b/src/profiler.cc
233
201
  @@ -63,6 +63,12 @@ typedef int ucontext_t; // just to quiet the compiler, mostly
@@ -283,7 +251,7 @@ index d158eea..e8509fe 100644
283
251
  #endif
284
252
  +#endif
285
253
  diff --git a/src/stacktrace_with_context.cc b/src/stacktrace_with_context.cc
286
- index 02f837d..ca5da92 100644
254
+ index ed7bfe3..a90c070 100644
287
255
  --- a/src/stacktrace_with_context.cc
288
256
  +++ b/src/stacktrace_with_context.cc
289
257
  @@ -41,6 +41,7 @@
@@ -1,7 +1,7 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'perftools.rb'
3
- s.version = '0.2.5'
4
- s.date = '2009-09-16'
3
+ s.version = '0.3.1'
4
+ s.date = '2009-10-10'
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'
@@ -9,22 +9,25 @@ spec = Gem::Specification.new do |s|
9
9
  s.homepage = "http://github.com/tmm1/perftools.rb"
10
10
 
11
11
  s.authors = ["Aman Gupta"]
12
- s.email = "aman@tmm1.net"
12
+ s.email = "perftools@tmm1.net"
13
13
 
14
14
  s.has_rdoc = false
15
15
  s.extensions = 'ext/extconf.rb'
16
16
  s.bindir = 'bin'
17
17
  s.executables << 'pprof.rb'
18
18
 
19
- # ruby -rpp -e' pp `git ls-files | grep -v examples`.split("\n") '
19
+ # ruby -rpp -e' pp `git ls-files | grep -v examples`.split("\n").sort '
20
20
  s.files = [
21
21
  "README",
22
22
  "bin/pprof.rb",
23
23
  "ext/extconf.rb",
24
24
  "ext/perftools.c",
25
+ "ext/src/google-perftools-1.4.tar.gz",
25
26
  "patches/perftools-debug.patch",
26
27
  "patches/perftools-gc.patch",
28
+ "patches/perftools-osx-106.patch",
27
29
  "patches/perftools-osx.patch",
30
+ "patches/perftools-pprof.patch",
28
31
  "patches/perftools.patch",
29
32
  "perftools.rb.gemspec"
30
33
  ]
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.2.5
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
@@ -9,12 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-16 00:00:00 -07:00
12
+ date: 2009-10-10 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
16
  description: A sampling profiler for ruby code based on patches to google-perftools
17
- email: aman@tmm1.net
17
+ email: perftools@tmm1.net
18
18
  executables:
19
19
  - pprof.rb
20
20
  extensions:
@@ -26,9 +26,12 @@ files:
26
26
  - bin/pprof.rb
27
27
  - ext/extconf.rb
28
28
  - ext/perftools.c
29
+ - ext/src/google-perftools-1.4.tar.gz
29
30
  - patches/perftools-debug.patch
30
31
  - patches/perftools-gc.patch
32
+ - patches/perftools-osx-106.patch
31
33
  - patches/perftools-osx.patch
34
+ - patches/perftools-pprof.patch
32
35
  - patches/perftools.patch
33
36
  - perftools.rb.gemspec
34
37
  has_rdoc: true