is_a 0.1.0 → 0.1.1

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/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