fat 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/benchmarks/fat.rb +136 -0
- data/ext/fat/fat.c +30 -30
- data/fat.gemspec +1 -1
- data/test/fat_test.rb +8 -7
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fffbd3df88760a30ab94ec780231688a17944655
|
4
|
+
data.tar.gz: 9bdbe4cff365157a89f42cde46e5de3b94112abc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39307004150f2606963b21e8f8adae44d269b2cb7f01142ff333fd6740a098f881672259c738f5282523330d2cfab6de452f8c330923f2569c42591212409144
|
7
|
+
data.tar.gz: 11adbb07becc3a42b6c480aa7fc23d5598142932f66e12b20b98604e8307b65f8fdcf62ee590ed46868c26f4c9f57a72dd926abb23d7034f286384f46bba18f4
|
data/benchmarks/fat.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require "benchmark/ips"
|
2
|
+
require_relative "../lib/fat"
|
3
|
+
|
4
|
+
class Hash
|
5
|
+
include Fat
|
6
|
+
|
7
|
+
def ruby_at(*args)
|
8
|
+
fields = args.length == 1 ? args[0].split(".") : args
|
9
|
+
value = self
|
10
|
+
|
11
|
+
fields.each do |field|
|
12
|
+
value = self[field]
|
13
|
+
return unless value
|
14
|
+
return value unless value.kind_of?(Hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
hash = {
|
22
|
+
"foo" => {
|
23
|
+
"bar" => {
|
24
|
+
"baz" => {
|
25
|
+
"key" => :value
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
puts "### String chain as a single argument."
|
32
|
+
Benchmark.ips do |bench|
|
33
|
+
bench.report("ruby") { hash.ruby_at("foo.bar.baz") }
|
34
|
+
bench.report("c") { hash.at("foo.bar.baz") }
|
35
|
+
bench.compare!
|
36
|
+
end
|
37
|
+
|
38
|
+
# ### String chain as a single argument.
|
39
|
+
# Calculating -------------------------------------
|
40
|
+
# ruby 47304 i/100ms
|
41
|
+
# c 55888 i/100ms
|
42
|
+
# -------------------------------------------------
|
43
|
+
# ruby 741487.1 (±10.6%) i/s - 3642408 in 5.002662s
|
44
|
+
# c 977630.9 (±11.3%) i/s - 4806368 in 5.001422s
|
45
|
+
# Comparison:
|
46
|
+
# c: 977630.9 i/s
|
47
|
+
# ruby: 741487.1 i/s - 1.32x slower
|
48
|
+
|
49
|
+
puts "### Each key as an argument."
|
50
|
+
Benchmark.ips do |bench|
|
51
|
+
bench.report("ruby") { hash.ruby_at("foo", "bar", "baz") }
|
52
|
+
bench.report("c") { hash.at("foo", "bar", "baz") }
|
53
|
+
bench.compare!
|
54
|
+
end
|
55
|
+
|
56
|
+
# ### Each key as an argument.
|
57
|
+
# Calculating -------------------------------------
|
58
|
+
# ruby 57145 i/100ms
|
59
|
+
# c 73161 i/100ms
|
60
|
+
# -------------------------------------------------
|
61
|
+
# ruby 1035908.2 (±9.7%) i/s - 5143050 in 5.036346s
|
62
|
+
# c 1513478.5 (±11.1%) i/s - 7462422 in 5.017305s
|
63
|
+
# Comparison:
|
64
|
+
# c: 1513478.5 i/s
|
65
|
+
# ruby: 1035908.2 i/s - 1.46x slower
|
66
|
+
|
67
|
+
puts "### No value found."
|
68
|
+
Benchmark.ips do |bench|
|
69
|
+
bench.report("ruby") { hash.ruby_at("foo.one.key") }
|
70
|
+
bench.report("c") { hash.at("foo.one.key") }
|
71
|
+
bench.compare!
|
72
|
+
end
|
73
|
+
|
74
|
+
# ### No value found.
|
75
|
+
# Calculating -------------------------------------
|
76
|
+
# ruby 46842 i/100ms
|
77
|
+
# c 62515 i/100ms
|
78
|
+
# -------------------------------------------------
|
79
|
+
# ruby 733070.0 (±10.0%) i/s - 3653676 in 5.052594s
|
80
|
+
# c 1103249.9 (±11.2%) i/s - 5438805 in 5.026985s
|
81
|
+
# Comparison:
|
82
|
+
# c: 1103249.9 i/s
|
83
|
+
# ruby: 733070.0 i/s - 1.50x slower
|
84
|
+
|
85
|
+
deep_hash = {
|
86
|
+
"foo" => {
|
87
|
+
"bar" => {
|
88
|
+
"baz" => {
|
89
|
+
"and" => {
|
90
|
+
"one" => {
|
91
|
+
"more" => {
|
92
|
+
"key" => :value
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
puts "### Deep hash - String chain argument."
|
102
|
+
Benchmark.ips do |bench|
|
103
|
+
bench.report("ruby") { deep_hash.ruby_at("foo.bar.baz.and.one.more.key") }
|
104
|
+
bench.report("c") { deep_hash.at("foo.bar.baz.and.one.more.key") }
|
105
|
+
bench.compare!
|
106
|
+
end
|
107
|
+
|
108
|
+
# ### Deep hash - String chain argument.
|
109
|
+
# Calculating -------------------------------------
|
110
|
+
# ruby 35209 i/100ms
|
111
|
+
# c 37201 i/100ms
|
112
|
+
# -------------------------------------------------
|
113
|
+
# ruby 490384.6 (±10.9%) i/s - 2429421 in 5.040102s
|
114
|
+
# c 530276.4 (±10.0%) i/s - 2641271 in 5.057748s
|
115
|
+
# Comparison:
|
116
|
+
# c: 530276.4 i/s
|
117
|
+
# ruby: 490384.6 i/s - 1.08x slower
|
118
|
+
|
119
|
+
puts "### Deep hash - Each key as an argument."
|
120
|
+
Benchmark.ips do |bench|
|
121
|
+
bench.report("ruby") { deep_hash.ruby_at("foo", "bar", "baz", "and", "one", "more", "key") }
|
122
|
+
bench.report("c") { deep_hash.at("foo", "bar", "baz", "and", "one", "more", "key") }
|
123
|
+
bench.compare!
|
124
|
+
end
|
125
|
+
|
126
|
+
# ### Deep hash - Each key as an argument.
|
127
|
+
# Calculating -------------------------------------
|
128
|
+
# ruby 44009 i/100ms
|
129
|
+
# c 46413 i/100ms
|
130
|
+
# -------------------------------------------------
|
131
|
+
# ruby 674854.4 (±10.2%) i/s - 3344684 in 5.040045s
|
132
|
+
# c 734889.3 (±8.5%) i/s - 3666627 in 5.039101s
|
133
|
+
# Comparison:
|
134
|
+
# c: 734889.3 i/s
|
135
|
+
# ruby: 674854.4 i/s - 1.09x slower
|
136
|
+
|
data/ext/fat/fat.c
CHANGED
@@ -13,8 +13,10 @@ static VALUE method_fetch_at(int argc, VALUE *argv, VALUE hash);
|
|
13
13
|
static VALUE fat(VALUE hash, VALUE fields, int raise_on_nil);
|
14
14
|
|
15
15
|
// Helpers
|
16
|
-
static void parse_fields(VALUE args, VALUE *fields);
|
17
|
-
static VALUE fields_upto_index(VALUE fields,
|
16
|
+
static inline void parse_fields(VALUE args, VALUE *fields);
|
17
|
+
static inline VALUE fields_upto_index(VALUE fields, long index);
|
18
|
+
static inline void parse_singleton_args(int argc, VALUE *argv, VALUE *hash, VALUE *fields);
|
19
|
+
static inline void parse_method_args(int argc, VALUE *argv, VALUE *fields);
|
18
20
|
|
19
21
|
void Init_fat(void) {
|
20
22
|
Fat = rb_define_module("Fat");
|
@@ -27,44 +29,34 @@ void Init_fat(void) {
|
|
27
29
|
|
28
30
|
static VALUE singleton_method_at(int argc, VALUE *argv, VALUE self) {
|
29
31
|
VALUE hash;
|
30
|
-
VALUE args;
|
31
|
-
|
32
|
-
rb_scan_args(argc, argv, "1*", &hash, &args);
|
33
|
-
|
34
32
|
VALUE fields;
|
35
|
-
|
33
|
+
|
34
|
+
parse_singleton_args(argc, argv, &hash, &fields);
|
36
35
|
|
37
36
|
return fat(hash, fields, 0);
|
38
37
|
}
|
39
38
|
|
40
39
|
static VALUE singleton_method_fetch_at(int argc, VALUE *argv, VALUE self) {
|
41
40
|
VALUE hash;
|
42
|
-
VALUE args;
|
43
|
-
|
44
|
-
rb_scan_args(argc, argv, "1*", &hash, &args);
|
45
|
-
|
46
41
|
VALUE fields;
|
47
|
-
|
42
|
+
|
43
|
+
parse_singleton_args(argc, argv, &hash, &fields);
|
48
44
|
|
49
45
|
return fat(hash, fields, 1);
|
50
46
|
}
|
51
47
|
|
52
48
|
static VALUE method_at(int argc, VALUE *argv, VALUE hash) {
|
53
|
-
VALUE args;
|
54
|
-
rb_scan_args(argc, argv, "*", &args);
|
55
|
-
|
56
49
|
VALUE fields;
|
57
|
-
|
50
|
+
|
51
|
+
parse_method_args(argc, argv, &fields);
|
58
52
|
|
59
53
|
return fat(hash, fields, 0);
|
60
54
|
}
|
61
55
|
|
62
56
|
static VALUE method_fetch_at(int argc, VALUE *argv, VALUE hash) {
|
63
|
-
VALUE args;
|
64
|
-
rb_scan_args(argc, argv, "*", &args);
|
65
|
-
|
66
57
|
VALUE fields;
|
67
|
-
|
58
|
+
|
59
|
+
parse_method_args(argc, argv, &fields);
|
68
60
|
|
69
61
|
return fat(hash, fields, 1);
|
70
62
|
}
|
@@ -72,12 +64,11 @@ static VALUE method_fetch_at(int argc, VALUE *argv, VALUE hash) {
|
|
72
64
|
static VALUE fat(VALUE hash, VALUE fields, int raise_on_nil) {
|
73
65
|
VALUE value = hash;
|
74
66
|
|
75
|
-
for (
|
76
|
-
|
77
|
-
value = rb_hash_aref(value, key);
|
67
|
+
for (long i = 0; i < RARRAY_LEN(fields); i++) {
|
68
|
+
value = rb_hash_aref(value, RARRAY_AREF(fields, i));
|
78
69
|
|
79
70
|
if (value == Qnil) {
|
80
|
-
if (raise_on_nil
|
71
|
+
if (raise_on_nil) {
|
81
72
|
rb_raise(rb_eKeyError, "No value found at %s", RSTRING_PTR(fields_upto_index(fields, i)));
|
82
73
|
} else {
|
83
74
|
return Qnil;
|
@@ -92,19 +83,28 @@ static VALUE fat(VALUE hash, VALUE fields, int raise_on_nil) {
|
|
92
83
|
return value;
|
93
84
|
}
|
94
85
|
|
95
|
-
static void parse_fields(VALUE args, VALUE *fields) {
|
86
|
+
static inline void parse_fields(VALUE args, VALUE *fields) {
|
96
87
|
if (RARRAY_LEN(args) == 1) {
|
97
|
-
|
98
|
-
|
99
|
-
StringValue(chain);
|
100
|
-
*fields = rb_str_split(chain, ".");
|
88
|
+
*fields = rb_str_split(RARRAY_PTR(args)[0], ".");
|
101
89
|
} else {
|
102
90
|
*fields = args;
|
103
91
|
}
|
104
92
|
}
|
105
93
|
|
106
|
-
static VALUE fields_upto_index(VALUE fields,
|
94
|
+
static inline VALUE fields_upto_index(VALUE fields, long index) {
|
107
95
|
VALUE range = rb_range_new(INT2FIX(0), INT2FIX(index), 0);
|
108
96
|
VALUE slice = rb_funcall(fields, rb_intern("slice"), 1, range);
|
109
97
|
return rb_ary_join(slice, rb_str_new2("."));
|
110
98
|
}
|
99
|
+
|
100
|
+
static inline void parse_singleton_args(int argc, VALUE *argv, VALUE *hash, VALUE *fields) {
|
101
|
+
VALUE args;
|
102
|
+
rb_scan_args(argc, argv, "1*", hash, &args);
|
103
|
+
parse_fields(args, fields);
|
104
|
+
}
|
105
|
+
|
106
|
+
static inline void parse_method_args(int argc, VALUE *argv, VALUE *fields) {
|
107
|
+
VALUE args;
|
108
|
+
rb_scan_args(argc, argv, "*", &args);
|
109
|
+
parse_fields(args, fields);
|
110
|
+
}
|
data/fat.gemspec
CHANGED
data/test/fat_test.rb
CHANGED
@@ -44,21 +44,22 @@ end
|
|
44
44
|
scope do
|
45
45
|
setup do
|
46
46
|
Hash.include(Fat)
|
47
|
-
end
|
48
|
-
|
49
|
-
test "include the module" do
|
50
|
-
assert Hash.new.respond_to?(:at)
|
51
|
-
end
|
52
47
|
|
53
|
-
|
54
|
-
hash = {
|
48
|
+
{
|
55
49
|
"foo" => {
|
56
50
|
"bar" => {
|
57
51
|
"baz" => :found
|
58
52
|
}
|
59
53
|
}
|
60
54
|
}
|
55
|
+
end
|
56
|
+
|
57
|
+
test "include the module" do |hash|
|
58
|
+
assert hash.respond_to?(:at)
|
59
|
+
assert hash.respond_to?(:fetch_at)
|
60
|
+
end
|
61
61
|
|
62
|
+
test "honor Fat interface" do |hash|
|
62
63
|
assert_equal :found, hash.at("foo", "bar", "baz")
|
63
64
|
assert_equal :found, hash.at("foo.bar.baz")
|
64
65
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lucas Tolchinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cutest
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- Makefile
|
53
53
|
- README.md
|
54
54
|
- Rakefile
|
55
|
+
- benchmarks/fat.rb
|
55
56
|
- ext/fat/extconf.rb
|
56
57
|
- ext/fat/fat.c
|
57
58
|
- fat.gemspec
|