hashugar 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -26,39 +26,42 @@ Let's compare to the competitors - [OpenStruct](http://www.ruby-doc.org/stdlib-1
26
26
 
27
27
  `$ rake bench`
28
28
 
29
- Ruby 1.9.3 benchmark
29
+ Ruby 2.1.3 benchmark
30
30
 
31
- OpenStruct create small hash and access once
32
- 43858.0 (±5.5%) i/s - 221820 in 5.074250s (cycle=3697)
33
- Hashr create small hash and access once
34
- 67408.9 (±5.0%) i/s - 339780 in 5.053728s (cycle=5663)
35
- Hashugar create small hash and access once
36
- 230217.9 (±4.2%) i/s - 1152670 in 5.015705s (cycle=15790)
37
-
38
- OpenStruct create big hash and access once
39
- 974.84.9%) i/s - 4949 in 5.090937s (cycle=101)
40
- Hashr create big hash and access once
41
- 3468.1 (±5.9%) i/s - 17450 in 5.051485s (cycle=349)
42
- Hashugar create big hash and access once
43
- 12738.32.6%) i/s - 64220 in 5.045018s (cycle=1235)
44
-
45
- OpenStruct create small hash and access ten times
46
- 46170.2 (±2.7%) i/s - 231362 in 5.014712s (cycle=3989)
47
- Hashr create small hash and access ten times
48
- 41818.8 (±2.5%) i/s - 210320 in 5.032433s (cycle=3824)
49
- Hashugar create small hash and access ten times
50
- 82216.8 (±2.3%) i/s - 411742 in 5.010785s (cycle=7099)
31
+ ```
32
+ OpenStruct create small hash and access once
33
+ 110766.3 (±4.7%) i/s - 557010 in 5.039303s
34
+ Hashr create small hash and access once
35
+ 147007.1 (±2.6%) i/s - 742596 in 5.054958s
36
+ Hashugar create small hash and access once
37
+ 427133.4 (±2.7%) i/s - 2157935 in 5.055919s
38
+ OpenStruct create big hash and access once
39
+ 2018.77.8%) i/s - 10050 in 5.005609s
40
+ Hashr create big hash and access once
41
+ 5021.04.5%) i/s - 25143 in 5.016474s
42
+ Hashugar create big hash and access once
43
+ 14542.731.7%) i/s - 65232 in 5.113105s
44
+ OpenStruct create small hash and access ten times
45
+ 100424.9 (±5.0%) i/s - 509004 in 5.080745s
46
+ Hashr create small hash and access ten times
47
+ 86539.9 (±3.7%) i/s - 433116 in 5.011856s
48
+ Hashugar create small hash and access ten times
49
+ 166080.6 (±2.6%) i/s - 844704 in 5.089568s
50
+ OpenStruct create small hash and access fifty times
51
+ 70585.2 (±5.0%) i/s - 356460 in 5.062517s
52
+ Hashr create small hash and access fifty times
53
+ 32565.7 (±2.4%) i/s - 164788 in 5.063123s
54
+ Hashugar create small hash and access fifty times
55
+ 46460.1 (±4.0%) i/s - 233677 in 5.038378s
56
+ OpenStruct create small hash and access hundred times
57
+ 51480.7 (±4.1%) i/s - 261131 in 5.081082s
58
+ Hashr create small hash and access hundred times
59
+ 18201.2 (±2.3%) i/s - 91443 in 5.026730s
60
+ Hashugar create small hash and access hundred times
61
+ 24413.4 (±2.0%) i/s - 124185 in 5.088771s
62
+ ```
51
63
 
52
- OpenStruct create small hash and access fifty times
53
- 36126.0 (±2.8%) i/s - 182112 in 5.044983s (cycle=3252)
54
- Hashr create small hash and access fifty times
55
- 15584.9 (±2.5%) i/s - 78312 in 5.028076s (cycle=1506)
56
- Hashugar create small hash and access fifty times
57
- 21513.9 (±6.0%) i/s - 107952 in 5.039238s (cycle=2076)
64
+ Why is it so fast?
65
+ ------------------
58
66
 
59
- OpenStruct create small hash and access hundred times
60
- 28617.9 (±2.7%) i/s - 144928 in 5.068069s (cycle=2588)
61
- Hashr create small hash and access hundred times
62
- 8860.7 (±1.7%) i/s - 45103 in 5.091664s (cycle=851)
63
- Hashugar create small hash and access hundred times
64
- 11491.3 (±2.4%) i/s - 57512 in 5.007677s (cycle=1106)
67
+ [OpenStruct defines a method using metaprogramming](https://github.com/ruby/ruby/blob/trunk/lib/ostruct.rb#L166-L173) on first access, but this is a slow operation. [Hashr is converting whole hash on initialization](https://github.com/svenfuchs/hashr/blob/master/lib/hashr.rb#L102-L114) which is slower when you don't need to access all keys and nested keys. Hashugar uses `method_missing`, which is slower in the long run, but faster for short-lived objects, it's also lazy so there is no precomputation/conversion step.
data/Rakefile CHANGED
@@ -15,27 +15,27 @@ task :bench do
15
15
  require 'hashugar'
16
16
 
17
17
  SMALL_HASH = {:a => 1, :b => 2}
18
- BIG_HASH = {}; 100.times {|i| BIG_HASH[i.to_s] = "item#{i}" }
18
+ BIG_HASH = {}; 100.times {|i| BIG_HASH["item#{i}"] = "item#{i}" }
19
19
 
20
20
  Benchmark.ips do |x|
21
- x.report 'OpenStruct create small hash and access once', 'OpenStruct.new(SMALL_HASH).item5'
22
- x.report 'Hashr create small hash and access once', 'Hashr.new(SMALL_HASH).item5'
23
- x.report 'Hashugar create small hash and access once', 'Hashugar.new(SMALL_HASH).item5'
21
+ x.report 'OpenStruct create small hash and access once', 'OpenStruct.new(SMALL_HASH).a'
22
+ x.report 'Hashr create small hash and access once', 'Hashr.new(SMALL_HASH).a'
23
+ x.report 'Hashugar create small hash and access once', 'Hashugar.new(SMALL_HASH).a'
24
24
 
25
- x.report 'OpenStruct create big hash and access once', 'OpenStruct.new(BIG_HASH).item5'
26
- x.report 'Hashr create big hash and access once', 'Hashr.new(BIG_HASH).item5'
27
- x.report 'Hashugar create big hash and access once', 'Hashugar.new(BIG_HASH).item5'
25
+ x.report 'OpenStruct create big hash and access once', 'OpenStruct.new(BIG_HASH).item50'
26
+ x.report 'Hashr create big hash and access once', 'Hashr.new(BIG_HASH).item50'
27
+ x.report 'Hashugar create big hash and access once', 'Hashugar.new(BIG_HASH).item50'
28
28
 
29
29
  x.report 'OpenStruct create small hash and access ten times', 'h = OpenStruct.new(SMALL_HASH); i = 0; while i < 10; h.a; i += 1; end'
30
- x.report 'Hashr create small hash and access ten times', 'h = Hashr.new(SMALL_HASH); i = 0; while i < 10; h.a; i += 1; end'
31
- x.report 'Hashugar create small hash and access ten times', 'h = Hashugar.new(SMALL_HASH); i = 0; while i < 10; h.a; i += 1; end'
30
+ x.report 'Hashr create small hash and access ten times', 'h = Hashr.new(SMALL_HASH); i = 0; while i < 10; h.a; i += 1; end'
31
+ x.report 'Hashugar create small hash and access ten times', 'h = Hashugar.new(SMALL_HASH); i = 0; while i < 10; h.a; i += 1; end'
32
32
 
33
33
  x.report 'OpenStruct create small hash and access fifty times', 'h = OpenStruct.new(SMALL_HASH); i = 0; while i < 50; h.a; i += 1; end'
34
- x.report 'Hashr create small hash and access fifty times', 'h = Hashr.new(SMALL_HASH); i = 0; while i < 50; h.a; i += 1; end'
35
- x.report 'Hashugar create small hash and access fifty times', 'h = Hashugar.new(SMALL_HASH); i = 0; while i < 50; h.a; i += 1; end'
34
+ x.report 'Hashr create small hash and access fifty times', 'h = Hashr.new(SMALL_HASH); i = 0; while i < 50; h.a; i += 1; end'
35
+ x.report 'Hashugar create small hash and access fifty times', 'h = Hashugar.new(SMALL_HASH); i = 0; while i < 50; h.a; i += 1; end'
36
36
 
37
37
  x.report 'OpenStruct create small hash and access hundred times', 'h = OpenStruct.new(SMALL_HASH); i = 0; while i < 100; h.a; i += 1; end'
38
- x.report 'Hashr create small hash and access hundred times', 'h = Hashr.new(SMALL_HASH); i = 0; while i < 100; h.a; i += 1; end'
39
- x.report 'Hashugar create small hash and access hundred times', 'h = Hashugar.new(SMALL_HASH); i = 0; while i < 100; h.a; i += 1; end'
38
+ x.report 'Hashr create small hash and access hundred times', 'h = Hashr.new(SMALL_HASH); i = 0; while i < 100; h.a; i += 1; end'
39
+ x.report 'Hashugar create small hash and access hundred times', 'h = Hashugar.new(SMALL_HASH); i = 0; while i < 100; h.a; i += 1; end'
40
40
  end
41
41
  end
@@ -1,3 +1,3 @@
1
1
  class Hashugar
2
- VERSION = "0.0.6"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/hashugar.rb CHANGED
@@ -7,33 +7,29 @@ class Hashugar
7
7
  hash.each_pair do |key, value|
8
8
  hashugar = value.to_hashugar
9
9
  @table_with_original_keys[key] = hashugar
10
- @table[convert_key(key)] = hashugar
10
+ @table[stringify(key)] = hashugar
11
11
  end
12
12
  end
13
13
 
14
14
  def method_missing(method, *args, &block)
15
15
  method = method.to_s
16
16
  if method.chomp!('=')
17
- self[method] = args.first
17
+ @table[method] = args.first
18
18
  else
19
19
  @table[method]
20
20
  end
21
21
  end
22
22
 
23
23
  def [](key)
24
- @table[convert_key(key)]
24
+ @table[stringify(key)]
25
25
  end
26
26
 
27
27
  def []=(key, value)
28
- @table[convert_key(key)] = value
29
- end
30
-
31
- def to_hashugar
32
- self
28
+ @table[stringify(key)] = value
33
29
  end
34
30
 
35
31
  def respond_to?(key)
36
- @table.has_key?(convert_key(key))
32
+ @table.has_key?(stringify(key))
37
33
  end
38
34
 
39
35
  def each(&block)
@@ -41,7 +37,7 @@ class Hashugar
41
37
  end
42
38
 
43
39
  private
44
- def convert_key(key)
40
+ def stringify(key)
45
41
  key.is_a?(Symbol) ? key.to_s : key
46
42
  end
47
43
  end
@@ -54,8 +50,7 @@ end
54
50
 
55
51
  class Array
56
52
  def to_hashugar
57
- # TODO lazy?
58
- Array.new(collect(&:to_hashugar))
53
+ map(&:to_hashugar)
59
54
  end
60
55
  end
61
56
 
@@ -4,73 +4,73 @@ describe Hashugar do
4
4
  context 'when accessing simple hash' do
5
5
  it 'should be make accessible string and symbol keys' do
6
6
  hashugar = {:a => 1, 'b' => 2}.to_hashugar
7
- hashugar.a.should == 1
8
- hashugar.b.should == 2
7
+ expect(hashugar.a).to eq(1)
8
+ expect(hashugar.b).to eq(2)
9
9
  end
10
10
 
11
11
  it 'should be readable through nice methods' do
12
12
  hashugar = {:a => 1, :b => 2}.to_hashugar
13
- hashugar.a.should == 1
14
- hashugar.b.should == 2
13
+ expect(hashugar.a).to eq(1)
14
+ expect(hashugar.b).to eq(2)
15
15
  end
16
16
 
17
17
  it 'should be writable through nice methods' do
18
18
  hashugar = {:a => 1}.to_hashugar
19
19
  hashugar.a = 2
20
20
  hashugar.b = 3
21
- hashugar.a.should == 2
22
- hashugar.b.should == 3
21
+ expect(hashugar.a).to eq(2)
22
+ expect(hashugar.b).to eq(3)
23
23
  end
24
24
 
25
25
  it 'should be readable through old methods' do
26
26
  hashugar = {:a => 1}.to_hashugar
27
- hashugar[:a].should == 1
28
- hashugar['a'].should == 1
27
+ expect(hashugar[:a]).to eq(1)
28
+ expect(hashugar['a']).to eq(1)
29
29
  end
30
30
 
31
31
  it 'should be writable through old methods' do
32
32
  hashugar = {:a => 1}.to_hashugar
33
33
  hashugar['a'] = 2
34
- hashugar.a.should == 2
34
+ expect(hashugar.a).to eq(2)
35
35
  hashugar[:a] = 3
36
- hashugar.a.should == 3
36
+ expect(hashugar.a).to eq(3)
37
37
  end
38
38
  end
39
39
 
40
40
  context 'when accessing nested hash' do
41
41
  it 'should be writable through nice methods' do
42
42
  hashugar = {:a => {:b => 1}}.to_hashugar
43
- hashugar.a.b.should == 1
43
+ expect(hashugar.a.b).to eq(1)
44
44
  end
45
45
 
46
46
  it 'should be writable through nice methods' do
47
47
  hashugar = {:a =>{}}.to_hashugar
48
48
  hashugar.a.b = 1
49
- hashugar.a.b.should == 1
49
+ expect(hashugar.a.b).to eq(1)
50
50
  end
51
51
  end
52
52
 
53
53
  context 'when accessing hashes in array' do
54
54
  it 'should return hashugars' do
55
55
  hashugar = [{:a => 1}, {:b => 2}].to_hashugar
56
- hashugar[0].a.should == 1
57
- hashugar.last.b.should == 2
56
+ expect(hashugar[0].a).to eq(1)
57
+ expect(hashugar.last.b).to eq(2)
58
58
  end
59
59
  end
60
60
 
61
61
  context 'when using respond_to?' do
62
62
  it 'should return true on valid key' do
63
63
  hashugar = {:a => 1}.to_hashugar
64
- hashugar.respond_to?('a').should be_true
65
- hashugar.respond_to?(:a).should be_true
66
- hashugar.respond_to?(:b).should be_false
64
+ expect(hashugar.respond_to?('a')).to be_truthy
65
+ expect(hashugar.respond_to?(:a)).to be_truthy
66
+ expect(hashugar.respond_to?(:b)).to be_falsey
67
67
  end
68
68
  end
69
69
 
70
70
  context 'when creating using Hashugar#new' do
71
71
  it 'should accept hash in contructor' do
72
72
  hashugar = Hashugar.new({:a => {:b => 1}})
73
- hashugar.a.b.should == 1
73
+ expect(hashugar.a.b).to eq(1)
74
74
  end
75
75
  end
76
76
 
@@ -85,8 +85,8 @@ describe Hashugar do
85
85
  values << v
86
86
  end
87
87
 
88
- keys.should == [:a, :c]
89
- values.should == [4, 2]
88
+ expect(keys).to eq([:a, :c])
89
+ expect(values).to eq([4, 2])
90
90
  end
91
91
  end
92
92
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hashugar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-06 00:00:00.000000000 Z
12
+ date: 2014-11-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &19350000 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *19350000
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: benchmark_suite
27
- requirement: &19348020 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *19348020
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: ffi
38
- requirement: &19365580 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *19365580
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: hashr
49
- requirement: &19674140 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,7 +69,12 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *19674140
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  description: Nested OpenStruct optimized for short-lived objects.
59
79
  email:
60
80
  - johno@jsmf.net
@@ -94,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
114
  version: '0'
95
115
  requirements: []
96
116
  rubyforge_project:
97
- rubygems_version: 1.8.15
117
+ rubygems_version: 1.8.23.2
98
118
  signing_key:
99
119
  specification_version: 3
100
120
  summary: Fast Nested OpenStruct