rblineprof 0.3.3.beta → 0.3.3
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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +16 -0
- data/README.md +8 -0
- data/Rakefile +31 -0
- data/ext/extconf.rb +6 -1
- data/ext/rblineprof.c +43 -20
- data/rblineprof.gemspec +3 -1
- data/test.rb +11 -7
- data/test/test_lineprof.rb +33 -0
- metadata +18 -15
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a6c7319f8169d091dde957717561a5776edfec3e
|
4
|
+
data.tar.gz: a39aa28cc67dbe8084b68085ec8ce495fdcf3655
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 26059d9a1c174f9fa1721bc66ae6339ac0727b0164f7f9df8f973315a64bb8e94f359db6461a50f083e7a6abb772ad113fbf8a7041d72eb13459d6efe90daf33
|
7
|
+
data.tar.gz: 56f634c3c42af0a5b040fb68c2eeb11f45561f2c6613781f8a84d86a80843dcb74ef6f97d55e7b4786923a0a19f734490c62ba61af5c62c6a9b62f020a3ba139
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
CHANGED
@@ -31,6 +31,10 @@
|
|
31
31
|
| end
|
32
32
|
```
|
33
33
|
|
34
|
+
### Rails integration
|
35
|
+
|
36
|
+
* [peek-rblineprof](https://github.com/peek/peek-rblineprof#peekrblineprof)
|
37
|
+
|
34
38
|
## Other profilers
|
35
39
|
|
36
40
|
* [PLine](https://github.com/soba1104/PLine) line-profiler for ruby 1.9
|
@@ -39,3 +43,7 @@
|
|
39
43
|
* [ruby-prof](https://github.com/rdp/ruby-prof)
|
40
44
|
* [perftools.rb](https://github.com/tmm1/perftools.rb)
|
41
45
|
* [zenprofile](https://github.com/seattlerb/zenprofile)
|
46
|
+
|
47
|
+
## License
|
48
|
+
|
49
|
+
rblineprof is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
task :default => :test
|
2
|
+
|
3
|
+
# ==========================================================
|
4
|
+
# Packaging
|
5
|
+
# ==========================================================
|
6
|
+
|
7
|
+
GEMSPEC = eval(File.read('rblineprof.gemspec'))
|
8
|
+
|
9
|
+
require 'rubygems/package_task'
|
10
|
+
Gem::PackageTask.new(GEMSPEC) do |pkg|
|
11
|
+
end
|
12
|
+
|
13
|
+
# ==========================================================
|
14
|
+
# Ruby Extension
|
15
|
+
# ==========================================================
|
16
|
+
|
17
|
+
require 'rake/extensiontask'
|
18
|
+
Rake::ExtensionTask.new('rblineprof', GEMSPEC) do |ext|
|
19
|
+
ext.ext_dir = 'ext'
|
20
|
+
end
|
21
|
+
task :build => :compile
|
22
|
+
|
23
|
+
# ==========================================================
|
24
|
+
# Testing
|
25
|
+
# ==========================================================
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new 'test' do |t|
|
29
|
+
t.test_files = FileList['test/test_*.rb']
|
30
|
+
end
|
31
|
+
task :test => :build
|
data/ext/extconf.rb
CHANGED
@@ -2,7 +2,12 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
have_func('rb_os_allocated_objects')
|
4
4
|
|
5
|
-
if RUBY_VERSION >= "1
|
5
|
+
if RUBY_VERSION >= "2.1"
|
6
|
+
have_func('rb_gc_stat')
|
7
|
+
have_func('rb_profile_frames')
|
8
|
+
have_func('rb_tracepoint_new')
|
9
|
+
create_makefile 'rblineprof'
|
10
|
+
elsif RUBY_VERSION >= "1.9"
|
6
11
|
require "debugger/ruby_core_source"
|
7
12
|
|
8
13
|
hdrs = proc {
|
data/ext/rblineprof.c
CHANGED
@@ -4,15 +4,19 @@
|
|
4
4
|
#include <sys/time.h>
|
5
5
|
#include <sys/resource.h>
|
6
6
|
|
7
|
-
#
|
7
|
+
#if defined(RUBY_VM)
|
8
8
|
#include <ruby/re.h>
|
9
|
+
#include <ruby/debug.h>
|
9
10
|
#include <ruby/intern.h>
|
10
|
-
#include <vm_core.h>
|
11
|
-
#include <iseq.h>
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
#if !defined(HAVE_RB_PROFILE_FRAMES)
|
13
|
+
#include <vm_core.h>
|
14
|
+
#include <iseq.h>
|
15
|
+
|
16
|
+
// There's a compile error on 1.9.3. So:
|
17
|
+
#ifdef RTYPEDDATA_DATA
|
18
|
+
#define ruby_current_thread ((rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current()))
|
19
|
+
#endif
|
16
20
|
#endif
|
17
21
|
#else
|
18
22
|
#include <st.h>
|
@@ -28,6 +32,7 @@ size_t rb_os_allocated_objects(void);
|
|
28
32
|
#endif
|
29
33
|
|
30
34
|
static VALUE gc_hook;
|
35
|
+
static VALUE sym_total_allocated_object;
|
31
36
|
|
32
37
|
/*
|
33
38
|
* Time in microseconds
|
@@ -40,7 +45,7 @@ typedef uint64_t prof_time_t;
|
|
40
45
|
typedef struct snapshot {
|
41
46
|
prof_time_t wall_time;
|
42
47
|
prof_time_t cpu_time;
|
43
|
-
#
|
48
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS) || defined(HAVE_RB_GC_STAT)
|
44
49
|
size_t allocated_objects;
|
45
50
|
#endif
|
46
51
|
} snapshot_t;
|
@@ -78,7 +83,9 @@ typedef struct sourcefile {
|
|
78
83
|
typedef struct stackframe {
|
79
84
|
// data emitted from Ruby to our profiler hook
|
80
85
|
rb_event_flag_t event;
|
81
|
-
#
|
86
|
+
#if defined(HAVE_RB_PROFILE_FRAMES)
|
87
|
+
VALUE thread;
|
88
|
+
#elif defined(RUBY_VM)
|
82
89
|
rb_thread_t *thread;
|
83
90
|
#else
|
84
91
|
NODE *node;
|
@@ -162,7 +169,7 @@ snapshot_diff(snapshot_t *t1, snapshot_t *t2)
|
|
162
169
|
snapshot_t diff = {
|
163
170
|
.wall_time = t1->wall_time - t2->wall_time,
|
164
171
|
.cpu_time = t1->cpu_time - t2->cpu_time,
|
165
|
-
#
|
172
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS) || defined(HAVE_RB_GC_STAT)
|
166
173
|
.allocated_objects = t1->allocated_objects - t2->allocated_objects
|
167
174
|
#endif
|
168
175
|
};
|
@@ -175,7 +182,7 @@ snapshot_increment(snapshot_t *s, snapshot_t *inc)
|
|
175
182
|
{
|
176
183
|
s->wall_time += inc->wall_time;
|
177
184
|
s->cpu_time += inc->cpu_time;
|
178
|
-
#
|
185
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS) || defined(HAVE_RB_GC_STAT)
|
179
186
|
s->allocated_objects += inc->allocated_objects;
|
180
187
|
#endif
|
181
188
|
}
|
@@ -277,7 +284,7 @@ sourcefile_lookup(char *filename)
|
|
277
284
|
return srcfile;
|
278
285
|
}
|
279
286
|
|
280
|
-
#
|
287
|
+
#if defined(RUBY_VM) && !defined(HAVE_RB_PROFILE_FRAMES)
|
281
288
|
/* Find the source of the current method call. This is based on rb_f_caller
|
282
289
|
* in vm_eval.c, and replicates the behavior of `caller.first` from ruby.
|
283
290
|
*
|
@@ -343,7 +350,17 @@ profiler_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE klass
|
|
343
350
|
* we use ruby_current_node here to get the caller's file/line info,
|
344
351
|
* (as opposed to node, which points to the callee method being invoked)
|
345
352
|
*/
|
346
|
-
#
|
353
|
+
#if defined(HAVE_RB_PROFILE_FRAMES)
|
354
|
+
int l;
|
355
|
+
VALUE iseq, path;
|
356
|
+
rb_profile_frames(0, 1, &iseq, &l);
|
357
|
+
|
358
|
+
/* TODO: use fstring VALUE directly */
|
359
|
+
path = rb_profile_frame_absolute_path(iseq);
|
360
|
+
if (!RTEST(path)) path = rb_profile_frame_path(iseq);
|
361
|
+
file = RSTRING_PTR(path);
|
362
|
+
line = l;
|
363
|
+
#elif !defined(RUBY_VM)
|
347
364
|
NODE *caller_node = ruby_frame->node;
|
348
365
|
if (!caller_node) return;
|
349
366
|
|
@@ -390,8 +407,10 @@ profiler_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE klass
|
|
390
407
|
snapshot_t now = {
|
391
408
|
.wall_time = walltime_usec(),
|
392
409
|
.cpu_time = cputime_usec(),
|
393
|
-
#
|
410
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS)
|
394
411
|
.allocated_objects = rb_os_allocated_objects()
|
412
|
+
#elif defined(HAVE_RB_GC_STAT)
|
413
|
+
.allocated_objects = rb_gc_stat(sym_total_allocated_object)
|
395
414
|
#endif
|
396
415
|
};
|
397
416
|
|
@@ -415,7 +434,9 @@ profiler_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE klass
|
|
415
434
|
frame->line = line;
|
416
435
|
frame->start = now;
|
417
436
|
frame->srcfile = srcfile;
|
418
|
-
#
|
437
|
+
#if defined(HAVE_RB_PROFILE_FRAMES)
|
438
|
+
frame->thread = rb_thread_current();
|
439
|
+
#elif defined(RUBY_VM)
|
419
440
|
frame->thread = th;
|
420
441
|
#else
|
421
442
|
frame->node = node;
|
@@ -462,7 +483,9 @@ profiler_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE klass
|
|
462
483
|
if (rblineprof.stack_depth > 0)
|
463
484
|
rblineprof.stack_depth--;
|
464
485
|
} while (frame &&
|
465
|
-
#
|
486
|
+
#if defined(HAVE_RB_PROFILE_FRAMES)
|
487
|
+
frame->thread != rb_thread_current() &&
|
488
|
+
#elif defined(RUBY_VM)
|
466
489
|
frame->thread != th &&
|
467
490
|
#endif
|
468
491
|
/* Break when we find a matching CALL/C_CALL.
|
@@ -531,7 +554,7 @@ summarize_files(st_data_t key, st_data_t record, st_data_t arg)
|
|
531
554
|
long i;
|
532
555
|
|
533
556
|
rb_ary_store(ary, 0, rb_ary_new3(
|
534
|
-
#
|
557
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS) || defined(HAVE_RB_GC_STAT)
|
535
558
|
7,
|
536
559
|
#else
|
537
560
|
6,
|
@@ -542,14 +565,14 @@ summarize_files(st_data_t key, st_data_t record, st_data_t arg)
|
|
542
565
|
ULL2NUM(srcfile->total.cpu_time),
|
543
566
|
ULL2NUM(srcfile->child.cpu_time),
|
544
567
|
ULL2NUM(srcfile->exclusive.cpu_time)
|
545
|
-
#
|
568
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS) || defined(HAVE_RB_GC_STAT)
|
546
569
|
, ULL2NUM(srcfile->total.allocated_objects)
|
547
570
|
#endif
|
548
571
|
));
|
549
572
|
|
550
573
|
for (i=1; i<srcfile->nlines; i++)
|
551
574
|
rb_ary_store(ary, i, rb_ary_new3(
|
552
|
-
#
|
575
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS) || defined(HAVE_RB_GC_STAT)
|
553
576
|
4,
|
554
577
|
#else
|
555
578
|
3,
|
@@ -557,7 +580,7 @@ summarize_files(st_data_t key, st_data_t record, st_data_t arg)
|
|
557
580
|
ULL2NUM(srcfile->lines[i].total.wall_time),
|
558
581
|
ULL2NUM(srcfile->lines[i].total.cpu_time),
|
559
582
|
ULL2NUM(srcfile->lines[i].calls)
|
560
|
-
#
|
583
|
+
#if defined(HAVE_RB_OS_ALLOCATED_OBJECTS) || defined(HAVE_RB_GC_STAT)
|
561
584
|
, ULL2NUM(srcfile->lines[i].total.allocated_objects)
|
562
585
|
#endif
|
563
586
|
));
|
@@ -621,7 +644,6 @@ lineprof(VALUE self, VALUE filename)
|
|
621
644
|
rb_ensure(rb_yield, Qnil, lineprof_ensure, self);
|
622
645
|
|
623
646
|
VALUE ret = rb_hash_new();
|
624
|
-
VALUE ary = Qnil;
|
625
647
|
|
626
648
|
if (rblineprof.source_filename) {
|
627
649
|
summarize_files(Qnil, (st_data_t)&rblineprof.file, ret);
|
@@ -642,6 +664,7 @@ rblineprof_gc_mark()
|
|
642
664
|
void
|
643
665
|
Init_rblineprof()
|
644
666
|
{
|
667
|
+
sym_total_allocated_object = ID2SYM(rb_intern("total_allocated_object"));
|
645
668
|
gc_hook = Data_Wrap_Struct(rb_cObject, rblineprof_gc_mark, NULL, NULL);
|
646
669
|
rb_global_variable(&gc_hook);
|
647
670
|
|
data/rblineprof.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rblineprof'
|
3
|
-
s.version = '0.3.3
|
3
|
+
s.version = '0.3.3'
|
4
4
|
s.homepage = 'http://github.com/tmm1/rblineprof'
|
5
5
|
|
6
6
|
s.authors = 'Aman Gupta'
|
@@ -12,5 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = 'line-profiler for ruby'
|
13
13
|
s.description = 'rblineprof shows you lines of code that are slow.'
|
14
14
|
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
15
17
|
s.add_dependency 'debugger-ruby_core_source', '~> 1.2'
|
16
18
|
end
|
data/test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
$:.unshift '
|
1
|
+
$:.unshift 'lib'
|
2
2
|
require 'rblineprof'
|
3
3
|
|
4
4
|
class Obj
|
@@ -108,16 +108,20 @@ profile = lineprof(/./) do
|
|
108
108
|
('a'..'z').to_a
|
109
109
|
end
|
110
110
|
|
111
|
+
allocation_mode = false
|
112
|
+
|
111
113
|
File.readlines(file).each_with_index do |line, num|
|
112
114
|
wall, cpu, calls, allocations = profile[file][num+1]
|
113
115
|
|
114
|
-
if
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
if allocation_mode
|
117
|
+
if allocations > 0
|
118
|
+
printf "% 10d objs | %s", allocations, line
|
119
|
+
else
|
120
|
+
printf " | %s", line
|
121
|
+
end
|
119
122
|
|
120
|
-
|
123
|
+
next
|
124
|
+
end
|
121
125
|
|
122
126
|
if calls && calls > 0
|
123
127
|
printf "% 8.1fms + % 8.1fms (% 5d) | %s", cpu/1000.0, (wall-cpu)/1000.0, calls, line
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'rblineprof'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class LineProfTest < Test::Unit::TestCase
|
6
|
+
def test_real
|
7
|
+
profile = lineprof(/./) do
|
8
|
+
sleep 0.001
|
9
|
+
end
|
10
|
+
|
11
|
+
line = profile[__FILE__][__LINE__-3]
|
12
|
+
assert_in_delta 1000, line[0], 600
|
13
|
+
assert_equal 1, line[2]
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_cpu
|
17
|
+
profile = lineprof(/./) do
|
18
|
+
(fibonacci = Hash.new{ |h,k| h[k] = k < 2 ? k : h[k-1] + h[k-2] })[500]
|
19
|
+
end
|
20
|
+
|
21
|
+
line = profile[__FILE__][__LINE__-3]
|
22
|
+
assert_operator line[1], :>=, 800
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_objects
|
26
|
+
profile = lineprof(/./) do
|
27
|
+
100.times{ "str" }
|
28
|
+
end
|
29
|
+
|
30
|
+
line = profile[__FILE__][__LINE__-3]
|
31
|
+
assert_equal 100, line[3]
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rblineprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.3
|
5
|
-
prerelease: 6
|
4
|
+
version: 0.3.3
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Aman Gupta
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-02 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: debugger-ruby_core_source
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '1.2'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '1.2'
|
30
27
|
description: rblineprof shows you lines of code that are slow.
|
@@ -34,34 +31,40 @@ extensions:
|
|
34
31
|
- ext/extconf.rb
|
35
32
|
extra_rdoc_files: []
|
36
33
|
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- Gemfile
|
36
|
+
- Gemfile.lock
|
37
37
|
- README.md
|
38
|
+
- Rakefile
|
38
39
|
- ext/.gitignore
|
39
40
|
- ext/extconf.rb
|
40
41
|
- ext/rblineprof.c
|
41
42
|
- rblineprof.gemspec
|
42
43
|
- test.rb
|
44
|
+
- test/test_lineprof.rb
|
43
45
|
homepage: http://github.com/tmm1/rblineprof
|
44
|
-
licenses:
|
46
|
+
licenses:
|
47
|
+
- MIT
|
48
|
+
metadata: {}
|
45
49
|
post_install_message:
|
46
50
|
rdoc_options: []
|
47
51
|
require_paths:
|
48
52
|
- lib
|
49
53
|
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
54
|
requirements:
|
52
|
-
- -
|
55
|
+
- - ">="
|
53
56
|
- !ruby/object:Gem::Version
|
54
57
|
version: '0'
|
55
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
-
none: false
|
57
59
|
requirements:
|
58
|
-
- -
|
60
|
+
- - ">="
|
59
61
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
62
|
+
version: '0'
|
61
63
|
requirements: []
|
62
64
|
rubyforge_project:
|
63
|
-
rubygems_version:
|
65
|
+
rubygems_version: 2.2.0.rc.1
|
64
66
|
signing_key:
|
65
|
-
specification_version:
|
67
|
+
specification_version: 4
|
66
68
|
summary: line-profiler for ruby
|
67
69
|
test_files: []
|
70
|
+
has_rdoc:
|