perftools.rb 0.4.5 → 0.4.6

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.
Files changed (3) hide show
  1. data/ext/perftools.c +48 -29
  2. data/perftools.rb.gemspec +1 -1
  3. metadata +13 -4
data/ext/perftools.c CHANGED
@@ -1,3 +1,5 @@
1
+ #include <ruby.h> // include this before anything else, as it defines _GNU_SOURCE etc
2
+
1
3
  #ifndef _GNU_SOURCE
2
4
  #define _GNU_SOURCE
3
5
  #endif
@@ -6,13 +8,13 @@
6
8
  #endif
7
9
 
8
10
  #include <assert.h>
9
- #include <ruby.h>
10
11
 
11
12
  void ProfilerGcMark(void (*cb)(VALUE));
12
- int ProfilerStart(const char*);
13
+ int ProfilerStart(const char*);
13
14
  void ProfilerStop();
14
15
  void ProfilerFlush();
15
16
  void ProfilerRecord(int, void*, void*);
17
+ int ProfilingIsEnabledForAllThreads();
16
18
 
17
19
  static VALUE Iallocate;
18
20
  static VALUE I__send__;
@@ -213,6 +215,7 @@ static VALUE objprofiler_teardown();
213
215
 
214
216
  static VALUE cPerfTools;
215
217
  static VALUE cCpuProfiler;
218
+ static VALUE eError;
216
219
  static VALUE bProfilerRunning;
217
220
  static VALUE gc_hook;
218
221
 
@@ -229,12 +232,10 @@ cpuprofiler_stop(VALUE self)
229
232
  return Qfalse;
230
233
 
231
234
  bProfilerRunning = Qfalse;
235
+ objprofiler_teardown();
232
236
  ProfilerStop();
233
237
  ProfilerFlush();
234
238
 
235
- if (getenv("CPUPROFILE_OBJECTS"))
236
- objprofiler_teardown();
237
-
238
239
  return Qtrue;
239
240
  }
240
241
 
@@ -244,13 +245,16 @@ cpuprofiler_start(VALUE self, VALUE filename)
244
245
  StringValue(filename);
245
246
 
246
247
  if (bProfilerRunning)
247
- return Qfalse;
248
+ rb_raise(eError, "profiler is already running");
248
249
 
249
250
  if (getenv("CPUPROFILE_OBJECTS"))
250
251
  objprofiler_setup();
251
252
 
252
- ProfilerStart(RSTRING_PTR(filename));
253
- bProfilerRunning = Qtrue;
253
+ if (ProfilerStart(RSTRING_PTR(filename))) {
254
+ bProfilerRunning = Qtrue;
255
+ } else {
256
+ rb_raise(eError, "profiler could not be started");
257
+ }
254
258
 
255
259
  if (rb_block_given_p()) {
256
260
  rb_yield(Qnil);
@@ -292,35 +296,36 @@ page_align(void *addr) {
292
296
  }
293
297
 
294
298
  static void
295
- unprotect_page(void *addr) {
299
+ unprotect_page(char *addr) {
296
300
  assert(addr != NULL);
297
- void *aligned_addr = page_align(addr);
301
+ char *aligned_addr = page_align(addr);
298
302
  if (mprotect(aligned_addr, (addr - aligned_addr), PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
299
303
  perror("mprotect");
300
304
  }
301
305
 
302
- static inline void**
306
+ static inline char**
303
307
  uc_get_ip(ucontext_t *uc) {
304
- #if defined(__FreeBSD__)
305
- return (void**)&uc->uc_mcontext.mc_rip;
306
- #elif defined(__dietlibc__)
307
- return (void**)&uc->uc_mcontext.rip;
308
- #elif defined(__APPLE__)
309
- #if defined(__LP64__)
310
- return (void**)&uc->uc_mcontext->__ss.__rip;
311
- #else
312
- return (void**)&uc->uc_mcontext->__ss.__eip;
313
- #endif
314
- #else
315
- return (void**)&uc->uc_mcontext.gregs[REG_RIP];
316
- #endif
308
+ # if defined(__FreeBSD__)
309
+ # define program_counter uc_mcontext.mc_rip
310
+ # elif defined(__dietlibc__)
311
+ # define program_counter uc_mcontext.rip
312
+ # elif defined(__APPLE__)
313
+ # ifdef __LP64__
314
+ # define program_counter uc_mcontext->__ss.__rip
315
+ # else
316
+ # define program_counter uc_mcontext->__ss.__eip
317
+ # endif
318
+ # else
319
+ # define program_counter uc_mcontext.gregs[REG_RIP]
320
+ # endif
321
+ return (char**)&uc->program_counter;
317
322
  }
318
323
 
319
324
  static void
320
325
  trap_handler(int sig, siginfo_t *info, void *data) {
321
326
  int i;
322
327
  ucontext_t *uc = (ucontext_t *)data;
323
- void **ip = uc_get_ip(uc);
328
+ char **ip = uc_get_ip(uc);
324
329
 
325
330
  // printf("signal: %d, addr: %p, ip: %p\n", signal, info->si_addr, *ip);
326
331
 
@@ -355,10 +360,10 @@ objprofiler_setup()
355
360
  sigemptyset(&sig.sa_mask);
356
361
  sigaction(SIGTRAP, &sig, NULL);
357
362
 
358
- unprotect_page(rb_newobj);
363
+ unprotect_page((char*)rb_newobj);
359
364
 
360
365
  for (i=0; i<NUM_ORIG_BYTES; i++) {
361
- orig_bytes[i].location = (char *)(rb_newobj + i);
366
+ orig_bytes[i].location = (char *)rb_newobj + i;
362
367
  orig_bytes[i].value = ((unsigned char*)rb_newobj)[i];
363
368
  orig_bytes[i].location[0] = '\xCC';
364
369
  }
@@ -390,10 +395,17 @@ objprofiler_teardown()
390
395
 
391
396
  /* Init */
392
397
 
398
+ static void
399
+ profiler_at_exit(VALUE self)
400
+ {
401
+ cpuprofiler_stop(self);
402
+ }
403
+
393
404
  void
394
405
  Init_perftools()
395
406
  {
396
407
  cPerfTools = rb_define_class("PerfTools", rb_cObject);
408
+ eError = rb_define_class_under(cPerfTools, "Error", rb_eStandardError);
397
409
  cCpuProfiler = rb_define_class_under(cPerfTools, "CpuProfiler", rb_cObject);
398
410
 
399
411
  Iallocate = rb_intern("allocate");
@@ -409,6 +421,13 @@ Init_perftools()
409
421
  gc_hook = Data_Wrap_Struct(cCpuProfiler, cpuprofiler_gc_mark, NULL, NULL);
410
422
  rb_global_variable(&gc_hook);
411
423
 
412
- if (getenv("CPUPROFILE") && getenv("CPUPROFILE_OBJECTS"))
413
- objprofiler_setup();
424
+ if (ProfilingIsEnabledForAllThreads()) { // profiler is already running?
425
+ bProfilerRunning = Qtrue;
426
+
427
+ if (getenv("CPUPROFILE_OBJECTS")) { // want to profile objects
428
+ objprofiler_setup();
429
+ }
430
+
431
+ rb_set_end_proc(profiler_at_exit, 0); // make sure to cleanup before the VM shuts down
432
+ }
414
433
  }
data/perftools.rb.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'perftools.rb'
3
- s.version = '0.4.5'
3
+ s.version = '0.4.6'
4
4
  s.date = '2010-08-03'
5
5
  s.rubyforge_project = 'perftools-rb'
6
6
  s.summary = 'google-perftools for ruby code'
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perftools.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 4
8
+ - 6
9
+ version: 0.4.6
5
10
  platform: ruby
6
11
  authors:
7
12
  - Aman Gupta
@@ -49,21 +54,25 @@ rdoc_options: []
49
54
  require_paths:
50
55
  - lib
51
56
  required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
52
58
  requirements:
53
59
  - - ">="
54
60
  - !ruby/object:Gem::Version
61
+ segments:
62
+ - 0
55
63
  version: "0"
56
- version:
57
64
  required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
58
66
  requirements:
59
67
  - - ">="
60
68
  - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
61
71
  version: "0"
62
- version:
63
72
  requirements: []
64
73
 
65
74
  rubyforge_project: perftools-rb
66
- rubygems_version: 1.3.5
75
+ rubygems_version: 1.3.7
67
76
  signing_key:
68
77
  specification_version: 3
69
78
  summary: google-perftools for ruby code