google_hash 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +39 -14
- data/VERSION +1 -1
- data/ext/extconf.rb +23 -13
- data/ext/temp/extconf.rb +11 -0
- data/ext/template/google_hash.cpp.erb +37 -9
- data/spec/spec.google_hash.rb +40 -17
- metadata +6 -4
data/README
CHANGED
@@ -28,26 +28,51 @@ See also the results.txt file
|
|
28
28
|
|
29
29
|
Usage:
|
30
30
|
|
31
|
-
a = GoogleHashDenseRubyToRuby.new
|
32
|
-
b = GoogleHashDenseIntToRuby.new # :int => Ruby
|
31
|
+
a = GoogleHashDenseRubyToRuby.new # like a normal Ruby hash, with slightly different performance characteristics, see benchmarks.txt
|
32
|
+
b = GoogleHashDenseIntToRuby.new # :int => Ruby -- keys are stored as "native" ints, values are ruby objects
|
33
33
|
c = GoogleHashSparseIntToInt.new # :int => :int
|
34
|
-
|
34
|
+
|
35
|
+
Here's the full list of availables:
|
36
|
+
|
37
|
+
>> Object.constants.each{|k k if k =~ /google/i }
|
38
|
+
|
39
|
+
GoogleHashDenseLongToLong
|
40
|
+
GoogleHashSparseLongToLong
|
41
|
+
GoogleHashDenseLongToInt
|
42
|
+
GoogleHashSparseLongToInt
|
43
|
+
GoogleHashDenseLongToRuby
|
44
|
+
GoogleHashSparseLongToRuby
|
45
|
+
GoogleHashDenseDoubleToLong
|
46
|
+
GoogleHashSparseDoubleToLong
|
47
|
+
GoogleHashDenseDoubleToInt
|
48
|
+
GoogleHashSparseDoubleToInt
|
49
|
+
GoogleHashDenseDoubleToRuby
|
50
|
+
GoogleHashSparseDoubleToRuby
|
51
|
+
GoogleHashDenseIntToLong
|
52
|
+
GoogleHashSparseIntToLong
|
53
|
+
GoogleHashDenseIntToInt
|
54
|
+
GoogleHashSparseIntToInt
|
55
|
+
GoogleHashDenseIntToRuby
|
56
|
+
GoogleHashSparseIntToRuby
|
57
|
+
GoogleHashDenseRubyToLong
|
58
|
+
GoogleHashSparseRubyToLong
|
59
|
+
GoogleHashDenseRubyToInt
|
60
|
+
GoogleHashSparseRubyToInt
|
61
|
+
GoogleHashDenseRubyToRuby
|
62
|
+
GoogleHashSparseRubyToRuby
|
63
|
+
|
64
|
+
(long is "better" than int on 64 bit systems only)
|
65
|
+
|
66
|
+
and how to use them:
|
35
67
|
|
36
68
|
a[3] = 4
|
37
69
|
b[4] = 'abc'
|
38
70
|
b['abc'] = 'some complex object'
|
39
71
|
c[3] = 4 # all you can use are ints...
|
40
72
|
|
41
|
-
|
42
|
-
|
43
|
-
a.keys
|
44
|
-
=> Array
|
45
|
-
a.values
|
46
|
-
=> Array
|
47
|
-
|
48
|
-
For a complete list, see types.txt, but it's all the various combinations of Ruby, Int, and Long.
|
73
|
+
Use them like "normal" hashes with the same method names.
|
49
74
|
|
50
|
-
To learn if sparse or dense is right for you, check
|
75
|
+
To learn if sparse or dense is right for you, check the documentation:
|
51
76
|
|
52
77
|
http://google-sparsehash.googlecode.com/svn/trunk/doc/index.html
|
53
78
|
Dense is faster, sparse uses less memory.
|
@@ -64,7 +89,7 @@ ex: currently it uses longs internally instead of ints--if you want ints or char
|
|
64
89
|
|
65
90
|
if you want it to remember insertion order, I could do that, too, or native "store away" strings/bignums, whatever.
|
66
91
|
|
67
|
-
Could also add vectors, vector(pairs), priority queues, floats, native bignums, other more complex types, if anybody
|
92
|
+
Could also add vectors, vector(pairs), priority queues, floats, native bignums, other more complex types, if anybody wants me to.
|
68
93
|
|
69
94
|
This is meant to be one more tool in the rubyists toolbelt when trying to optimize speed-wise, and plans to expand to more types, but at least with this release it has a #each method.
|
70
95
|
|
@@ -80,4 +105,4 @@ Related:
|
|
80
105
|
|
81
106
|
judy http://groups.google.com/group/ruby-talk-google/browse_thread/thread/05ed587925526a7f/314375891d12b672?lnk=raot
|
82
107
|
|
83
|
-
NArray gem : provides "native" type arrays (and X-
|
108
|
+
NArray gem : provides "native" type arrays (and X-Dimensional arrays--all in native memory, so also saves memory as this gem does)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/ext/extconf.rb
CHANGED
@@ -38,26 +38,35 @@ ruby_key = {:convert_keys_from_ruby => "", :convert_keys_to_ruby => "", :key_ty
|
|
38
38
|
:extra_hash_params => ", hashrb, eqrb", :unreachable_key => "current_instance"} # TODO NULL is false here?
|
39
39
|
int_key = {:assert_key_type => 'T_FIXNUM', :convert_keys_from_ruby => "FIX2INT",
|
40
40
|
:convert_keys_to_ruby => "INT2FIX", :key_type => "int", :unreachable_key => "1<<#{unreachable_int}"}
|
41
|
-
|
42
|
-
|
41
|
+
|
42
|
+
# "long" is useful on 64 bit...
|
43
|
+
long_key = {:assert_key_type => 'T_FIXNUM', :convert_keys_from_ruby => "FIX2LONG",
|
44
|
+
:convert_keys_to_ruby => "LONG2FIX", :key_type => "long", :unreachable_key => "1<<#{unreachable_int}"}
|
45
|
+
|
46
|
+
|
47
|
+
bignum_as_double_key = {:assert_key_type => ['T_BIGNUM', 'T_FIXNUM'], :convert_keys_from_ruby => "rb_big2dbl",
|
43
48
|
:convert_keys_to_ruby => "rb_dbl2big", :key_type => "double", :unreachable_key => "1<<#{unreachable_int}", # LODO is this a bignum value though?
|
44
49
|
:extra_hash_params => ", hashdouble, eqdouble",
|
45
|
-
:extra_set_code => "if(TYPE(set_this) == T_FIXNUM)\nset_this = rb_int2big(set_this);",
|
46
|
-
:extra_get_code => "if(TYPE(get_this) == T_FIXNUM) \n get_this = rb_int2big(get_this);"
|
47
|
-
}
|
48
|
-
|
50
|
+
:extra_set_code => "if(TYPE(set_this) == T_FIXNUM)\nset_this = rb_int2big(FIX2INT(set_this));",
|
51
|
+
:extra_get_code => "if(TYPE(get_this) == T_FIXNUM) \n get_this = rb_int2big(FIX2INT(get_this));"
|
52
|
+
}
|
49
53
|
|
50
54
|
ruby_value = {:value_type => "VALUE", :english_value_type => "ruby"}
|
51
55
|
int_value = {:assert_value_type => 'T_FIXNUM', :convert_values_from_ruby => "FIX2INT",
|
52
56
|
:convert_values_to_ruby => "INT2FIX", :value_type => "int"}
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
+
long_value = {:assert_value_type => 'T_FIXNUM', :convert_values_from_ruby => "FIX2LONG",
|
58
|
+
:convert_values_to_ruby => "LONG2FIX", :value_type => "long"}
|
59
|
+
|
60
|
+
bignum_as_double_value = {:assert_value_type => ['T_BIGNUM', 'T_FIXNUM'], :convert_values_from_ruby => "rb_big2dbl",
|
61
|
+
:convert_values_to_ruby => "rb_dbl2big", :value_type => "double",
|
62
|
+
:extra_set_code2 => "if(TYPE(to_this) == T_FIXNUM)\nto_this = rb_int2big(FIX2INT(to_this));"
|
63
|
+
}
|
64
|
+
|
65
|
+
|
57
66
|
init_funcs = []
|
58
67
|
|
59
|
-
for key in [ruby_key, int_key,
|
60
|
-
for value in [ruby_value, int_value] do
|
68
|
+
for key in [ruby_key, int_key, bignum_as_double_key, long_key] do
|
69
|
+
for value in [ruby_value, int_value, long_value, bignum_as_double_value] do
|
61
70
|
options = key.merge(value)
|
62
71
|
for type in ['sparse', 'dense'] do
|
63
72
|
|
@@ -75,7 +84,8 @@ for key in [ruby_key, int_key, bignum_key] do
|
|
75
84
|
assert_key_type2 = [options[:assert_key_type]].flatten[1]
|
76
85
|
convert_values_from_ruby = options[:convert_values_from_ruby]
|
77
86
|
convert_values_to_ruby = options[:convert_values_to_ruby]
|
78
|
-
assert_value_type = options[:assert_value_type]
|
87
|
+
assert_value_type = [options[:assert_value_type]].flatten[0]
|
88
|
+
assert_value_type2 = [options[:assert_value_type]].flatten[1]
|
79
89
|
|
80
90
|
extra_hash_params = options[:extra_hash_params]
|
81
91
|
|
data/ext/temp/extconf.rb
ADDED
@@ -73,9 +73,8 @@ struct hashdouble {
|
|
73
73
|
<% end %>
|
74
74
|
|
75
75
|
<% if key_type == 'VALUE' %>
|
76
|
-
static hash<const char*> H;
|
77
|
-
|
78
|
-
// hashing it is like hash<const char*>
|
76
|
+
// static hash<const char*> H; // unused currently...
|
77
|
+
// using it is like hash<const char*>
|
79
78
|
|
80
79
|
struct eqrb
|
81
80
|
{
|
@@ -213,18 +212,21 @@ static VALUE rb_ghash_set(VALUE cb, VALUE set_this, VALUE to_this) {
|
|
213
212
|
|
214
213
|
<% if assert_value_type %>
|
215
214
|
if(!(TYPE(to_this) == <%= assert_value_type %>)) {
|
215
|
+
<%= "if(!(TYPE(to_this) == #{assert_value_type2}))" if assert_value_type2 %>
|
216
216
|
rb_raise(rb_eTypeError, "not valid value <%=assert_value_type%>");
|
217
217
|
}
|
218
218
|
<% end %>
|
219
219
|
|
220
220
|
<%= options[:extra_set_code] %>
|
221
221
|
|
222
|
+
<%= options[:extra_set_code2] %>
|
223
|
+
|
222
224
|
RCallback* cbs = GetCallbackStruct(cb);
|
223
225
|
(*cbs->hash_map)[ <%= convert_keys_from_ruby %>(set_this)] = <%= convert_values_from_ruby %>(to_this);
|
224
226
|
return to_this; // ltodo test that it returns value...
|
225
227
|
}
|
226
228
|
|
227
|
-
static VALUE rb_ghash_get(VALUE cb, VALUE get_this) {
|
229
|
+
static VALUE rb_ghash_get(VALUE cb, VALUE get_this, int just_check_for_presence) {
|
228
230
|
// TODO optionally not type check assert anywhere [?]
|
229
231
|
<% if assert_key_type %>
|
230
232
|
if(!(TYPE(get_this) == <%= assert_key_type %>)) {
|
@@ -237,12 +239,33 @@ static VALUE rb_ghash_get(VALUE cb, VALUE get_this) {
|
|
237
239
|
|
238
240
|
<%= type %>_hash_map< <%= key_type %>, <%= value_type %> <%= extra_hash_params %> >::iterator out = cbs->hash_map->find(<%= convert_keys_from_ruby %>(get_this));
|
239
241
|
|
240
|
-
if(out == cbs->hash_map->end()) { // not found...hmm...is this False, though?
|
241
|
-
|
242
|
-
|
243
|
-
|
242
|
+
if(out == cbs->hash_map->end()) { // not found...hmm...is this False, though?
|
243
|
+
if(just_check_for_presence)
|
244
|
+
return Qfalse;
|
245
|
+
else
|
246
|
+
return Qnil;
|
247
|
+
} else {
|
248
|
+
if(just_check_for_presence)
|
249
|
+
return Qtrue;
|
250
|
+
else
|
251
|
+
return <%= convert_values_to_ruby %>(out->second);
|
244
252
|
}
|
253
|
+
|
245
254
|
}
|
255
|
+
|
256
|
+
static VALUE rb_ghash_get_value(VALUE cb, VALUE get_this) {
|
257
|
+
return rb_ghash_get(cb, get_this, 0);
|
258
|
+
}
|
259
|
+
|
260
|
+
static VALUE rb_ghash_get_present(VALUE cb, VALUE get_this) {
|
261
|
+
return rb_ghash_get(cb, get_this, 1);
|
262
|
+
}
|
263
|
+
|
264
|
+
static VALUE rb_ghash_size(VALUE cb) {
|
265
|
+
RCallback* incoming = GetCallbackStruct(cb);
|
266
|
+
return INT2FIX(incoming->hash_map->size());
|
267
|
+
}
|
268
|
+
|
246
269
|
|
247
270
|
static VALUE rb_ghash_each(VALUE cb) {
|
248
271
|
RCallback* incoming = GetCallbackStruct(cb);
|
@@ -299,11 +322,16 @@ void init_<%= type %>_<%= english_key_type %>_to_<%= english_value_type %>() {
|
|
299
322
|
|
300
323
|
rb_define_method(rb_cGoogleHashLocal, "initialize", RUBY_METHOD_FUNC(rb_mri_hash_new), 0);
|
301
324
|
rb_define_method(rb_cGoogleHashLocal, "[]=", RUBY_METHOD_FUNC(rb_ghash_set), 2);
|
302
|
-
rb_define_method(rb_cGoogleHashLocal, "[]", RUBY_METHOD_FUNC(
|
325
|
+
rb_define_method(rb_cGoogleHashLocal, "[]", RUBY_METHOD_FUNC(rb_ghash_get_value), 1);
|
303
326
|
rb_define_method(rb_cGoogleHashLocal, "each", RUBY_METHOD_FUNC(rb_ghash_each), 0);
|
304
327
|
rb_define_method(rb_cGoogleHashLocal, "values", RUBY_METHOD_FUNC(rb_ghash_values), 0);
|
305
328
|
rb_define_method(rb_cGoogleHashLocal, "keys", RUBY_METHOD_FUNC(rb_ghash_keys), 0);
|
329
|
+
rb_define_method(rb_cGoogleHashLocal, "has_key?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
330
|
+
rb_define_method(rb_cGoogleHashLocal, "key?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
331
|
+
rb_define_method(rb_cGoogleHashLocal, "member?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
332
|
+
rb_define_method(rb_cGoogleHashLocal, "include?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
306
333
|
rb_define_method(rb_cGoogleHashLocal, "keys_combination_2", RUBY_METHOD_FUNC(rb_ghash_combination_2), 0);
|
334
|
+
rb_define_method(rb_cGoogleHashLocal, "length", RUBY_METHOD_FUNC(rb_ghash_size), 0);
|
307
335
|
id_eql = rb_intern("eql?");
|
308
336
|
id_hash = rb_intern("hash");
|
309
337
|
}
|
data/spec/spec.google_hash.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require 'rubygems'
|
1
|
+
require 'rubygems'
|
2
2
|
require 'sane'
|
3
|
-
require_relative '../ext/google_hash
|
3
|
+
require_relative '../ext/google_hash'
|
4
4
|
begin
|
5
5
|
require 'spec/autorun'
|
6
6
|
rescue LoadError
|
@@ -13,8 +13,8 @@ describe "google_hash" do
|
|
13
13
|
@subject = GoogleHashSparseIntToRuby.new
|
14
14
|
end
|
15
15
|
|
16
|
-
it "should be instantiable" do
|
17
|
-
|
16
|
+
it "should be instantiable [new method should not raise]" do
|
17
|
+
GoogleHashSparseIntToRuby.new
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should allow you to set a key" do
|
@@ -36,23 +36,38 @@ describe "google_hash" do
|
|
36
36
|
assert all_got.sort == ['abc', 'def']
|
37
37
|
end
|
38
38
|
|
39
|
+
it "should have key methods" do
|
40
|
+
@subject = a = GoogleHashDenseDoubleToInt.new
|
41
|
+
@subject[33] = 3
|
42
|
+
for method in [:has_key?, :include?, :key?, :member?] do
|
43
|
+
@subject.send(method, 33).should == true
|
44
|
+
@subject.send(method, 34).should == false
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
39
49
|
it "should have all the methods desired" do
|
40
|
-
pending "need"
|
41
50
|
# guess these could all be tests, themselves...
|
42
|
-
@subject.each_key {}
|
43
|
-
@subject.each_value{}
|
44
51
|
@subject.each{}
|
45
52
|
@subject[33] = 'abc'
|
46
53
|
@subject.length.should == 1
|
54
|
+
@subject.each{}
|
55
|
+
@subject.each{|k, v|
|
56
|
+
k.should == 33
|
57
|
+
v.should == 'abc'
|
58
|
+
}
|
47
59
|
@subject.delete(33).should == 'abc'
|
60
|
+
@subject.length.should == 0
|
61
|
+
@subject[33] = 'abc'
|
62
|
+
@subject.length.should == 1
|
48
63
|
@subject.clear
|
49
64
|
@subject.length.should == 0
|
50
65
|
end
|
51
|
-
|
52
|
-
it "should not leak" do
|
53
|
-
pending "testing if it leaks"
|
54
|
-
end
|
55
66
|
|
67
|
+
it 'should not be able to set the absent key for double' do
|
68
|
+
fail
|
69
|
+
end
|
70
|
+
|
56
71
|
def populate(a)
|
57
72
|
a['abc'] = 'def'
|
58
73
|
a['bbc'] = 'yoyo'
|
@@ -109,8 +124,8 @@ describe "google_hash" do
|
|
109
124
|
pending "if necessary"
|
110
125
|
end
|
111
126
|
|
112
|
-
it "should do longs
|
113
|
-
|
127
|
+
it "should do longs" do
|
128
|
+
GoogleHashDenseLongToLong.new
|
114
129
|
end
|
115
130
|
|
116
131
|
it "should do 63 bit thingy for longs on 64 bit" do
|
@@ -169,6 +184,7 @@ describe "google_hash" do
|
|
169
184
|
end
|
170
185
|
|
171
186
|
it "should not leak" do
|
187
|
+
pending 'something that might leak'
|
172
188
|
a = GoogleHashDenseIntToInt.new
|
173
189
|
100_000.times {
|
174
190
|
a[1] = 1
|
@@ -186,25 +202,27 @@ describe "google_hash" do
|
|
186
202
|
end
|
187
203
|
|
188
204
|
it "should do float values as doubles" do
|
205
|
+
pending "interest in floats"
|
189
206
|
a = GoogleHashDenseDoubleToInt.new
|
190
207
|
a[1.0] = 1
|
191
208
|
a[1.0].should == 1
|
192
209
|
end
|
193
210
|
|
194
211
|
it "should do bignum to doubles et al" do
|
195
|
-
pending
|
196
212
|
a = GoogleHashDenseDoubleToDouble.new
|
197
213
|
a[10000000000000000000] = 1
|
198
214
|
a[10000000000000000000].should == 1
|
199
215
|
a[1] = 10000000000000000000
|
200
216
|
a[1].should == 10000000000000000000
|
217
|
+
a[4] = 3
|
218
|
+
a[4].should == 3
|
201
219
|
a[10000000000000000000] = 10000000000000000000
|
202
220
|
a[10000000000000000000].should == 10000000000000000000
|
203
221
|
end
|
204
222
|
|
205
|
-
it "should
|
223
|
+
it "should allow for storing true bignums" do
|
206
224
|
pending
|
207
|
-
fail 'same as above plus'
|
225
|
+
fail 'same as above plus the following:'
|
208
226
|
a = GoogleHashDenseBignumToRuby.new
|
209
227
|
a[10000000000000000000] = 'abc'
|
210
228
|
end
|
@@ -223,7 +241,12 @@ describe "google_hash" do
|
|
223
241
|
|
224
242
|
it "should have an Enumerator for values, keys, an on demand, getNext enumerator object..."
|
225
243
|
|
226
|
-
it "should have a block access for values, keys"
|
244
|
+
it "should have a block access for values, keys" do
|
245
|
+
pending "interest"
|
246
|
+
@a[3] = 4
|
247
|
+
a.each_value {}
|
248
|
+
a.each_key {}
|
249
|
+
end
|
227
250
|
|
228
251
|
it "should have sets, too, not just hashes"
|
229
252
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- rogerdpack
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-07-
|
17
|
+
date: 2010-07-27 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -36,6 +36,7 @@ executables: []
|
|
36
36
|
|
37
37
|
extensions:
|
38
38
|
- ext/extconf.rb
|
39
|
+
- ext/temp/extconf.rb
|
39
40
|
extra_rdoc_files:
|
40
41
|
- README
|
41
42
|
files:
|
@@ -128,6 +129,7 @@ files:
|
|
128
129
|
- spec/scale.rb
|
129
130
|
- spec/spec.google_hash.rb
|
130
131
|
- types.txt
|
132
|
+
- ext/temp/extconf.rb
|
131
133
|
has_rdoc: true
|
132
134
|
homepage: http://github.com/rdp/ruby_google_hash
|
133
135
|
licenses: []
|