perftools.rb 0.2.5 → 0.3.1

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