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