is_a 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -6,7 +6,9 @@ A small library of missing ruby methods for introspection. See Usage.
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
- gem 'is_a'
9
+ ```ruby
10
+ gem 'is_a'
11
+ ```
10
12
 
11
13
  And then execute:
12
14
 
@@ -42,7 +44,7 @@ ObjectSpace._id2ref(id) == obj # => true
42
44
  #For 1.9.3 use BasicObject#__id__
43
45
  ```
44
46
 
45
- ### Fast getting of lines from caller
47
+ ### Fast single line from caller
46
48
 
47
49
  Ruby's `caller` is handy, but sometimes you do not need the whole array of strings it allocates generates on each call.
48
50
 
@@ -61,9 +63,9 @@ end
61
63
  Results:
62
64
 
63
65
  ```
64
- user system total real
65
- caller[1] 0.430000 0.010000 0.440000 ( 0.443102)
66
- caller_line 0.010000 0.000000 0.010000 ( 0.002275)
66
+ user system total real
67
+ caller[1] 1.760000 0.040000 1.800000 ( 1.802799)
68
+ caller_line 0.080000 0.000000 0.080000 ( 0.089649)
67
69
  ```
68
70
 
69
71
 
data/Rakefile CHANGED
@@ -4,77 +4,33 @@ require "bundler/gem_tasks"
4
4
  require 'rake/extensiontask'
5
5
  Rake::ExtensionTask.new('is_a')
6
6
 
7
- desc "Simple dump test,just to check if extension compiles and does not segfault on simple dump"
8
- task :test => :compile do
7
+ require 'rake/testtask'
9
8
 
10
- #TODO: use some testing framework like minitest...
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.pattern = 'spec/**/*_spec.rb'
11
+ t.libs.push 'spec'
12
+ end
11
13
 
12
- require "bundler/setup"
13
- require 'is_a'
14
14
 
15
- class SomeDSL < BasicObject
16
- def initialize
17
- @search_me = 12345
18
- end
19
- def lala
20
- end
21
- end
15
+ desc "Simple dump test,just to check if extension compiles and does not segfault on simple dump"
16
+ task :test => :compile
22
17
 
23
- obj = SomeDSL.new
18
+ task :default => :test
24
19
 
25
- def cls obj
26
- cls = IsA.class_of(obj)
27
- cls1 = cls
28
- classes = []
29
- while cls = cls.superclass
30
- classes << cls
20
+ desc "Make simple benchmark for caller_line"
21
+ task :bench_caller_line do
22
+ require 'bundler/setup'
23
+ require 'is_a'
24
+ require 'benchmark'
25
+ n = 50000
26
+ class UtilClassWithCallerline
27
+ class << self
28
+ define_method :caller_line, method(:caller_line)
31
29
  end
32
-
33
- puts "Cls is #{cls1.inspect}, #{classes.inspect}"
34
- cls1
35
- end
36
-
37
- c = cls obj
38
- cls c
39
- cls nil
40
-
41
- id = IsA.id_of(obj)
42
- puts "Id is #{id}"
43
- if ObjectSpace._id2ref(id) == obj
44
- puts "Getref ok"
45
- else
46
- puts "Getref FAIL"
47
30
  end
48
-
49
- unless IsA.object?(obj)
50
- puts "object? ok"
51
- else
52
- puts "object? FAIL"
53
- end
54
-
55
- if IsA.object?(c)
56
- puts "object? ok"
57
- else
58
- puts "object? FAIL"
59
- end
60
-
61
- def test_caller
62
- puts "Real caller: #{caller[0]}"
63
- puts "Caller at 0: #{IsA.caller_line(0)}"
64
- puts caller_line
65
- end
66
-
67
- test_caller
68
-
69
- require 'benchmark'
70
- n = 10000
71
- Benchmark.bm(11) do |x|
31
+ Benchmark.bm(19) do |x|
72
32
  x.report("caller[1]") { n.times { caller[1] } }
73
33
  x.report("caller_line") { n.times { caller_line(1) } }
34
+ x.report("caller_line in ctx") { n.times { UtilClassWithCallerline.caller_line(1) } }
74
35
  end
75
-
76
- #require 'heap_dump'
77
- #HeapDump.dump
78
- end
79
-
80
- task :default => :test
36
+ end
@@ -35,13 +35,17 @@ static VALUE caller_line(int offset)
35
35
  rb_control_frame_t* cfp = th->cfp + offset;
36
36
  const rb_control_frame_t* stack_end = (void *)(th->stack + th->stack_size);
37
37
 
38
- if(cfp < stack_end){
38
+ VALUE name = 0;
39
+
40
+ while(cfp < stack_end){
39
41
  if (cfp->iseq != 0) {
40
42
  if (cfp->pc != 0) {
41
43
  rb_iseq_t *iseq = cfp->iseq;
42
44
  int line_no = rb_vm_get_sourceline(cfp);
43
- VALUE file = iseq->filename,
44
- name = iseq->name;
45
+ VALUE file = iseq->filename;
46
+ //name may be passed from previous iteration
47
+ if(!name)
48
+ name = iseq->name;
45
49
  if (line_no) {
46
50
  return rb_enc_sprintf(
47
51
  rb_enc_compatible(file, name),
@@ -55,12 +59,26 @@ static VALUE caller_line(int offset)
55
59
  }
56
60
  }
57
61
  } else {
58
- // printf("CFUNC\n");
59
- return Qnil;
62
+ // for CFUNCs - search for previous ruby frame for location
63
+ if (RUBYVM_CFUNC_FRAME_P(cfp)) {
64
+ if (!name){
65
+ ID id;
66
+ if (cfp->me->def)
67
+ id = cfp->me->def->original_id;
68
+ else
69
+ id = cfp->me->called_id;
70
+ if (id != ID_ALLOCATOR){
71
+ name = rb_id2str(id);
72
+ }
73
+ }
74
+ }
75
+ cfp += 1;
76
+ continue;
60
77
  }
61
- } else {
62
- // level is out of bounds
78
+ break;
63
79
  }
80
+
81
+ // level is out of bounds
64
82
  return Qnil;
65
83
  }
66
84
 
@@ -19,4 +19,5 @@ Gem::Specification.new do |gem|
19
19
 
20
20
  gem.add_dependency("debugger-ruby_core_source")
21
21
  gem.add_development_dependency "rake-compiler"
22
+ gem.add_development_dependency "minitest"
22
23
  end
@@ -1,3 +1,3 @@
1
1
  module IsA
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -0,0 +1,51 @@
1
+ require 'minitest/autorun'
2
+ require 'benchmark'
3
+ require 'is_a'
4
+
5
+ describe IsA do
6
+
7
+ subject { IsA }
8
+
9
+ it 'id_of' do
10
+ obj = Class.new(BasicObject){}.new
11
+
12
+ id = subject.id_of(obj)
13
+ assert_equal(obj, ObjectSpace._id2ref(id))
14
+ end
15
+
16
+ it "object?" do
17
+ subject.object?(Class.new(BasicObject){}.new).must_equal false
18
+ subject.object?("string is object").must_equal true
19
+ end
20
+
21
+ describe "caller_line" do
22
+ it "in methods" do
23
+ def test_caller
24
+ [caller[0], subject.caller_line(0)]
25
+ end
26
+ r = test_caller
27
+ r.first.must_equal r.last
28
+ end
29
+
30
+ it "in blocks" do
31
+ r = proc{
32
+ [caller[0], subject.caller_line(0)]
33
+ }.call
34
+ r.last.wont_be_nil
35
+ r.first.must_equal r.last
36
+ end
37
+
38
+ it "should be faster than caller[0]" do
39
+ n = 1000
40
+ anchor = Benchmark.measure{ n.times{ caller[0] } }
41
+ res = Benchmark.measure{ n.times{ subject.caller_line(0) } }
42
+ assert_operator res.total, :<, anchor.total
43
+ assert_operator res.real, :<, anchor.real
44
+ assert_operator res.utime, :<, anchor.utime
45
+
46
+ # no large memory allocation => no system cpu time
47
+ res.stime.must_equal 0.0
48
+ end
49
+ end
50
+
51
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: is_a
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-02 00:00:00.000000000 Z
12
+ date: 2013-07-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: debugger-ruby_core_source
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: minitest
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  description: Fear weak references to BasicObject no more
47
63
  email:
48
64
  - vasilyfedoseyev@gmail.com
@@ -61,6 +77,7 @@ files:
61
77
  - is_a.gemspec
62
78
  - lib/is_a.rb
63
79
  - lib/is_a/version.rb
80
+ - spec/is_a_spec.rb
64
81
  homepage: http://github.com/Vasfed/is_a
65
82
  licenses: []
66
83
  post_install_message:
@@ -75,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
92
  version: '0'
76
93
  segments:
77
94
  - 0
78
- hash: 3551024361612674054
95
+ hash: 2510194417071522637
79
96
  required_rubygems_version: !ruby/object:Gem::Requirement
80
97
  none: false
81
98
  requirements:
@@ -84,11 +101,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
101
  version: '0'
85
102
  segments:
86
103
  - 0
87
- hash: 3551024361612674054
104
+ hash: 2510194417071522637
88
105
  requirements: []
89
106
  rubyforge_project:
90
107
  rubygems_version: 1.8.24
91
108
  signing_key:
92
109
  specification_version: 3
93
110
  summary: Defines methods to introspect any ruby object more deeply
94
- test_files: []
111
+ test_files:
112
+ - spec/is_a_spec.rb