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.
- data/ext/perftools.c +48 -29
- data/perftools.rb.gemspec +1 -1
- 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
|
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
|
-
|
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
|
-
|
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(
|
299
|
+
unprotect_page(char *addr) {
|
296
300
|
assert(addr != NULL);
|
297
|
-
|
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
|
306
|
+
static inline char**
|
303
307
|
uc_get_ip(ucontext_t *uc) {
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
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
|
-
|
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 *)
|
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 (
|
413
|
-
|
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
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
|
-
|
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.
|
75
|
+
rubygems_version: 1.3.7
|
67
76
|
signing_key:
|
68
77
|
specification_version: 3
|
69
78
|
summary: google-perftools for ruby code
|