binding_ninja 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +66 -0
- data/benchmark.rb +38 -0
- data/ext/binding_ninja/binding_ninja.c +42 -7
- data/lib/binding_ninja.rb +30 -0
- data/lib/binding_ninja/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57eeb87ad943b9ab0093e5cbbd33ee92891a2180
|
4
|
+
data.tar.gz: 1a5246c9bdb73a8b83ed7f01c5f61c6882df4349
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fadddaa3dd7b0f6cb31bbb9c1f531f4777ec83315b843fe7655cbcf49399ba3ae8e50e3a7288f6637d30e082374d9965d97ef36d073fe2ff24dd49bef57bacc
|
7
|
+
data.tar.gz: f7c154b4bc8de3a28e39c02ec4dd2645e82724839e843bdd9d71b6ab3af7891c5aa545d52c2274ce1cc7b8ec694fdb20d6ccfb7c97566552d951d03add4ffd4f
|
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# BindingNinja
|
2
|
+
[](https://badge.fury.io/rb/binding_ninja)
|
2
3
|
[](https://travis-ci.org/joker1007/binding_ninja)
|
3
4
|
|
4
5
|
This is method wrapper for passing binding of method caller implcitly.
|
6
|
+
And this is lightweight alternative of [binding_of_caller](https://github.com/banister/binding_of_caller)
|
5
7
|
|
6
8
|
## Installation
|
7
9
|
|
@@ -64,6 +66,70 @@ Foo.new.foo2(1, 2)
|
|
64
66
|
`:if` option can accept Proc object and Symbol object.
|
65
67
|
If option accepts a proc or symbol, uses result of evaluating the proc or method named by the symbol.
|
66
68
|
|
69
|
+
## Compare to binding_of_caller
|
70
|
+
```ruby
|
71
|
+
require "benchmark/ips"
|
72
|
+
require "binding_ninja"
|
73
|
+
require "binding_of_caller"
|
74
|
+
|
75
|
+
class Foo
|
76
|
+
extend BindingNinja
|
77
|
+
|
78
|
+
auto_inject_binding def foo1(b)
|
79
|
+
b.local_variables
|
80
|
+
end
|
81
|
+
|
82
|
+
def foo2
|
83
|
+
binding.of_caller(1).local_variables
|
84
|
+
end
|
85
|
+
|
86
|
+
def foo3(b)
|
87
|
+
b.local_variables
|
88
|
+
end
|
89
|
+
auto_inject_binding :foo3, if: :enable_auto_inject_binding?
|
90
|
+
|
91
|
+
def enable_auto_inject_binding?
|
92
|
+
true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
foo = Foo.new
|
97
|
+
|
98
|
+
p foo.foo1
|
99
|
+
p foo.foo2
|
100
|
+
p foo.foo3
|
101
|
+
|
102
|
+
Benchmark.ips do |x|
|
103
|
+
x.report("binding_ninja") { foo.foo1 }
|
104
|
+
x.report("binding_ninja_with_condition") { foo.foo3 }
|
105
|
+
x.report("binding_of_caller") { foo.foo2 }
|
106
|
+
|
107
|
+
x.compare!
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
```
|
112
|
+
Warming up --------------------------------------
|
113
|
+
binding_ninja 106.598k i/100ms
|
114
|
+
binding_ninja_with_condition
|
115
|
+
49.660k i/100ms
|
116
|
+
binding_of_caller 6.799k i/100ms
|
117
|
+
Calculating -------------------------------------
|
118
|
+
binding_ninja 1.351M (± 0.4%) i/s - 6.822M in 5.051283s
|
119
|
+
binding_ninja_with_condition
|
120
|
+
566.555k (± 0.3%) i/s - 2.880M in 5.083895s
|
121
|
+
binding_of_caller 69.968k (± 0.8%) i/s - 353.548k in 5.053337s
|
122
|
+
|
123
|
+
Comparison:
|
124
|
+
binding_ninja: 1350619.1 i/s
|
125
|
+
binding_ninja_with_condition: 566555.1 i/s - 2.38x slower
|
126
|
+
binding_of_caller: 69968.2 i/s - 19.30x slower
|
127
|
+
|
128
|
+
```
|
129
|
+
|
130
|
+
13x - 16x faster than binding_of_caller.
|
131
|
+
And binding_ninja has very simple code base.
|
132
|
+
|
67
133
|
## Development
|
68
134
|
|
69
135
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/benchmark.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "benchmark/ips"
|
2
|
+
require "binding_ninja"
|
3
|
+
require "binding_of_caller"
|
4
|
+
|
5
|
+
class Foo
|
6
|
+
extend BindingNinja
|
7
|
+
|
8
|
+
auto_inject_binding def foo1(b)
|
9
|
+
b.local_variables
|
10
|
+
end
|
11
|
+
|
12
|
+
def foo2
|
13
|
+
binding.of_caller(1).local_variables
|
14
|
+
end
|
15
|
+
|
16
|
+
def foo3(b)
|
17
|
+
b.local_variables
|
18
|
+
end
|
19
|
+
auto_inject_binding :foo3, if: :enable_auto_inject_binding?
|
20
|
+
|
21
|
+
def enable_auto_inject_binding?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
foo = Foo.new
|
27
|
+
|
28
|
+
p foo.foo1
|
29
|
+
p foo.foo2
|
30
|
+
p foo.foo3
|
31
|
+
|
32
|
+
Benchmark.ips do |x|
|
33
|
+
x.report("binding_ninja") { foo.foo1 }
|
34
|
+
x.report("binding_ninja_with_condition") { foo.foo3 }
|
35
|
+
x.report("binding_of_caller") { foo.foo2 }
|
36
|
+
|
37
|
+
x.compare!
|
38
|
+
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
VALUE rb_mBindingNinja;
|
4
4
|
static VALUE auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self);
|
5
|
+
static VALUE auto_inject_binding_invoke_without_cond(int argc, VALUE *argv, VALUE self);
|
6
|
+
static VALUE auto_inject_binding_invoke_stub(int argc, VALUE *argv, VALUE self);
|
5
7
|
|
6
8
|
static ID options_id;
|
7
9
|
|
@@ -13,6 +15,8 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
|
|
13
15
|
static ID keyword_ids[1];
|
14
16
|
VALUE extensions, ext_mod, method_sym, options, opt, cond;
|
15
17
|
|
18
|
+
cond = Qundef;
|
19
|
+
|
16
20
|
if (!keyword_ids[0]) {
|
17
21
|
keyword_ids[0] = rb_intern("if");
|
18
22
|
}
|
@@ -21,11 +25,11 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
|
|
21
25
|
extensions_id = rb_intern("@auto_inject_binding_extensions");
|
22
26
|
}
|
23
27
|
|
24
|
-
if (
|
25
|
-
options =
|
28
|
+
if (rb_ivar_defined(mod, options_id)) {
|
29
|
+
options = rb_ivar_get(mod, options_id);
|
26
30
|
} else {
|
27
31
|
options = rb_hash_new();
|
28
|
-
|
32
|
+
rb_ivar_set(mod, options_id, options);
|
29
33
|
}
|
30
34
|
|
31
35
|
rb_scan_args(argc, argv, "1:", &method_sym, &opt);
|
@@ -51,7 +55,18 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
|
|
51
55
|
if (rb_mod_include_p(mod, ext_mod) == Qfalse) {
|
52
56
|
rb_prepend_module(mod, ext_mod);
|
53
57
|
}
|
54
|
-
|
58
|
+
|
59
|
+
if (cond == Qundef) {
|
60
|
+
rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke_without_cond, -1);
|
61
|
+
} else if (rb_obj_is_proc(cond) || SYMBOL_P(cond)) {
|
62
|
+
rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke, -1);
|
63
|
+
} else {
|
64
|
+
if (RTEST(cond)) {
|
65
|
+
rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke_without_cond, -1);
|
66
|
+
} else {
|
67
|
+
rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke_stub, -1);
|
68
|
+
}
|
69
|
+
}
|
55
70
|
|
56
71
|
return method_sym;
|
57
72
|
}
|
@@ -59,7 +74,7 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
|
|
59
74
|
static VALUE
|
60
75
|
auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self)
|
61
76
|
{
|
62
|
-
VALUE method_sym, options, binding, args_ary, cond;
|
77
|
+
VALUE method_sym, ext_mod, options, binding, args_ary, cond;
|
63
78
|
static VALUE dummy_proc_args, dummy_method_arg[0];
|
64
79
|
|
65
80
|
if (!dummy_proc_args) {
|
@@ -68,7 +83,7 @@ auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self)
|
|
68
83
|
}
|
69
84
|
|
70
85
|
method_sym = ID2SYM(rb_frame_this_func());
|
71
|
-
options =
|
86
|
+
options = rb_funcall(CLASS_OF(self), rb_intern("auto_inject_binding_options"), 0);
|
72
87
|
|
73
88
|
cond = rb_hash_lookup2(options, method_sym, Qtrue);
|
74
89
|
|
@@ -92,11 +107,31 @@ auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self)
|
|
92
107
|
return rb_call_super(argc + 1, RARRAY_CONST_PTR(args_ary));
|
93
108
|
}
|
94
109
|
|
110
|
+
|
111
|
+
static VALUE
|
112
|
+
auto_inject_binding_invoke_without_cond(int argc, VALUE *argv, VALUE self)
|
113
|
+
{
|
114
|
+
VALUE args_ary, binding;
|
115
|
+
args_ary = rb_ary_new_from_values(argc, argv);
|
116
|
+
binding = rb_binding_new();
|
117
|
+
rb_ary_unshift(args_ary, binding);
|
118
|
+
return rb_call_super(argc + 1, RARRAY_CONST_PTR(args_ary));
|
119
|
+
}
|
120
|
+
|
121
|
+
static VALUE
|
122
|
+
auto_inject_binding_invoke_stub(int argc, VALUE *argv, VALUE self)
|
123
|
+
{
|
124
|
+
VALUE args_ary;
|
125
|
+
args_ary = rb_ary_new_from_values(argc, argv);
|
126
|
+
rb_ary_unshift(args_ary, Qnil);
|
127
|
+
return rb_call_super(argc + 1, RARRAY_CONST_PTR(args_ary));
|
128
|
+
}
|
129
|
+
|
95
130
|
void
|
96
131
|
Init_binding_ninja(void)
|
97
132
|
{
|
98
133
|
rb_mBindingNinja = rb_define_module("BindingNinja");
|
99
|
-
options_id = rb_intern("
|
134
|
+
options_id = rb_intern("@auto_inject_binding_options");
|
100
135
|
rb_ivar_set(rb_mBindingNinja, rb_intern("@auto_inject_binding_extensions"), rb_hash_new());
|
101
136
|
rb_define_private_method(rb_mBindingNinja, "auto_inject_binding", auto_inject_binding, -1);
|
102
137
|
}
|
data/lib/binding_ninja.rb
CHANGED
@@ -2,4 +2,34 @@ require "binding_ninja/version"
|
|
2
2
|
require "binding_ninja/binding_ninja"
|
3
3
|
|
4
4
|
module BindingNinja
|
5
|
+
def auto_inject_binding_options
|
6
|
+
{}
|
7
|
+
end
|
8
|
+
|
9
|
+
METHOD_DEFINER = ->(klass) do
|
10
|
+
unless klass.method_defined?(:auto_inject_binding_options)
|
11
|
+
options = {}
|
12
|
+
klass.class_eval do
|
13
|
+
@auto_inject_binding_options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
klass.define_singleton_method(:auto_inject_binding_options) do
|
17
|
+
super().merge(options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def inherited(klass)
|
23
|
+
super
|
24
|
+
METHOD_DEFINER.call(klass)
|
25
|
+
end
|
26
|
+
|
27
|
+
def included(klass)
|
28
|
+
super
|
29
|
+
METHOD_DEFINER.call(klass)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.extended(klass)
|
33
|
+
METHOD_DEFINER.call(klass)
|
34
|
+
end
|
5
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: binding_ninja
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- joker1007
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- Gemfile
|
81
81
|
- README.md
|
82
82
|
- Rakefile
|
83
|
+
- benchmark.rb
|
83
84
|
- bin/console
|
84
85
|
- bin/setup
|
85
86
|
- binding_ninja.gemspec
|
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
108
|
version: '0'
|
108
109
|
requirements: []
|
109
110
|
rubyforge_project:
|
110
|
-
rubygems_version: 2.6.
|
111
|
+
rubygems_version: 2.6.13
|
111
112
|
signing_key:
|
112
113
|
specification_version: 4
|
113
114
|
summary: pass binding of method caller implicitly
|