ruby-tokyotyrant 0.4 → 0.5

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.
@@ -6,9 +6,7 @@ This is a c extension for Ruby to access TokyoTyrant databases. It currently su
6
6
 
7
7
  # install tokyocabinet (1.4.34) and tokyotyrant (requires 1.1.35)
8
8
  # after installing tc and tt on linux I had to /sbin/ldconfig (as root)
9
- sudo gem install gemcutter
10
- sudo gem tumble
11
- sudo gem install ruby-tokyotyrant
9
+ sudo gem install ruby-tokyotyrant --source=http://gemcutter.org
12
10
 
13
11
  == Performance
14
12
 
@@ -39,6 +37,28 @@ This is not in production but the initial benchmarks are very interesting. Resul
39
37
  db.mput("1"=>"number_1", "2"=>"number_2", "3"=>"number_3", "4"=>"number_4", "5"=>"number_5")
40
38
  db.mget(1..3) # => {"1"=>"number_1", "2"=>"number_2", "3"=>"number_3"}
41
39
 
40
+ === B+ Tree DB
41
+
42
+ # start tyrant like so:
43
+ # ttserver example.tcb
44
+
45
+ require 'tokyo_tyrant'
46
+ bdb = TokyoTyrant::BDB.new('127.0.0.1', 1978)
47
+
48
+ bdb.putdup('foo', 'bar')
49
+ # => true
50
+
51
+ bdb.putlist({ 'foo' => ['baz', 'bat']})
52
+ # => []
53
+
54
+ bdb.getlist('foo')
55
+ # => {"foo"=>["bar", "baz", "bat"]}
56
+
57
+ bdb.each{ |k,v| puts [k, v].inspect }
58
+ # ["foo", "bar"]
59
+ # ["foo", "baz"]
60
+ # ["foo", "bat"]
61
+
42
62
  === Table DB
43
63
 
44
64
  # start tyrant like so:
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ CLEAN.include('pkg', 'tmp')
20
20
 
21
21
  gemspec = Gem::Specification.new do |s|
22
22
  s.name = 'ruby-tokyotyrant'
23
- s.version = '0.4'
23
+ s.version = '0.5'
24
24
  s.authors = [ 'Flinn' ]
25
25
  s.email = 'flinn@actsasflinn.com'
26
26
  s.homepage = 'http://github.com/actsasflinn/ruby-tokyotyrant/'
@@ -35,12 +35,10 @@ gemspec = Gem::Specification.new do |s|
35
35
  'Rakefile',
36
36
  'README.rdoc'] +
37
37
  Dir['ext/**/*.[rb|c|h]'] +
38
- Dir['lib/**/*.rb'] +
38
+ Dir['ext/tokyo_tyrant/**/*.rb'] +
39
39
  Dir['spec/**/*'] +
40
40
  Dir['benchmarks/**/*']
41
41
  s.extensions << "ext/extconf.rb"
42
-
43
- s.add_runtime_dependency('fast_hash_ring', '>= 0.1.1')
44
42
  end
45
43
 
46
44
  task :gemspec do
@@ -53,7 +51,7 @@ Rake::GemPackageTask.new(gemspec) do |pkg|
53
51
  pkg.need_tar = true
54
52
  end
55
53
 
56
- Rake::PackageTask.new('ruby-tokyotyrant', '0.4') do |pkg|
54
+ Rake::PackageTask.new('ruby-tokyotyrant', '0.5') do |pkg|
57
55
  pkg.need_zip = true
58
56
  pkg.package_files = FileList[
59
57
  'COPYING',
@@ -1,3 +1,26 @@
1
+ =begin
2
+ Tokyo Tyrant Bulk Operations Benchmark
3
+
4
+
5
+ TokyoTyrant::RDB (Ruby) mget
6
+ user system total real
7
+ inserting data 7.770000 1.870000 9.640000 ( 12.598373)
8
+ reading data 1.540000 0.250000 1.790000 ( 2.290628)
9
+
10
+
11
+ TokyoTyrant (c) mput/mget
12
+ user system total real
13
+ inserting data 0.020000 0.000000 0.020000 ( 0.037996)
14
+ reading data 0.060000 0.010000 0.070000 ( 0.120651)
15
+
16
+
17
+ Memcached (C) set/get_multi
18
+ user system total real
19
+ inserting data* 0.160000 0.140000 0.300000 ( 0.884097)
20
+ reading data 0.090000 0.000000 0.090000 ( 0.140217)
21
+ * bulk operation not supported
22
+ =end
23
+
1
24
  require 'benchmark'
2
25
  require 'rubygems'
3
26
  require 'faker'
@@ -1,3 +1,31 @@
1
+ =begin
2
+ Tokyo Tyrant Bulk Table Operations Benchmark
3
+
4
+
5
+ TokyoTyrant (C)
6
+ user system total real
7
+ bulk writing data 0.180000 0.000000 0.180000 ( 0.292081)
8
+ bulk reading data 0.120000 0.020000 0.140000 ( 0.216074)
9
+
10
+
11
+ TokyoTyrant::RDB (Ruby)
12
+ user system total real
13
+ bulk inserting data* 42.410000 4.130000 46.540000 ( 63.657929)
14
+ bulk reading data 2.360000 0.280000 2.640000 ( 3.709915)
15
+
16
+
17
+ Mongo
18
+ user system total real
19
+ bulk writing data 27.860000 0.470000 28.330000 ( 37.619586)
20
+ bulk reading data 0.650000 0.100000 0.750000 ( 1.371567)
21
+
22
+ Notes:
23
+ * To supply a hash for bulk operations TokyoTyrant::RDB creates an array and join hash columns.
24
+ * This operation is included in the benchmark because the same code exists within the c-ext.
25
+ Rufus::Tokyo::TyrantTable does not support the misc method, therefor cannot handle a putlist/getlist
26
+ Memcached does not support bulk writing
27
+ =end
28
+
1
29
  require 'benchmark'
2
30
  require 'rubygems'
3
31
  require 'faker'
@@ -10,7 +38,7 @@ $month = (1..12).to_a
10
38
  $day = (1..28).to_a # not bothering with month diffs
11
39
 
12
40
  def rbdate
13
- DateTime.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
41
+ Date.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
14
42
  end
15
43
 
16
44
  def rdiv
@@ -30,9 +58,12 @@ end
30
58
 
31
59
  data = {}
32
60
  10_000.times do |i|
33
- data[i] = { :name => Faker::Name.name, :sex => rgen, :birthday => rbdate.to_s, :divisions => rdiv }
61
+ data[i.to_s] = { :_id => i.to_s, :name => Faker::Name.name, :sex => rgen, :birthday => rbdate.to_s, :divisions => rdiv }
34
62
  end
35
63
 
64
+ data_keys = data.keys
65
+ data_values = data.values
66
+
36
67
  require 'tokyo_tyrant'
37
68
  t = TokyoTyrant::Table.new('127.0.0.1', 45001)
38
69
  t.clear
@@ -46,7 +77,7 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
46
77
  end
47
78
 
48
79
  b.report('bulk reading data') do
49
- nothing = t.mget(0..9999)
80
+ nothing = t.mget(data_keys)
50
81
  end
51
82
  end
52
83
 
@@ -80,6 +111,23 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
80
111
  end
81
112
  end
82
113
 
114
+ require 'mongo'
115
+ db = Mongo::Connection.new.db("benchmark")
116
+ 2.times { puts }
117
+ puts 'Mongo'
118
+ mdb = db["data"]
119
+ mdb.remove
120
+
121
+ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
122
+ b.report('bulk writing data') do
123
+ nothing = mdb.insert(data_values)
124
+ end
125
+
126
+ b.report('bulk reading data') do
127
+ nothing = mdb.find(:_id => {'$in' => data_keys}).to_a
128
+ end
129
+ end
130
+
83
131
  puts "\nNotes:"
84
132
  puts "* To supply a hash for bulk operations TokyoTyrant::RDB creates an array and join hash columns."
85
133
  puts "* This operation is included in the benchmark because the same code exists within the c-ext."
@@ -1,14 +1,56 @@
1
+ =begin
2
+ Tokyo::Tyrant (Ruby FFI)
3
+ user system total real
4
+ inserting data 0.140000 0.180000 0.320000 ( 1.208150)
5
+ reading data 0.240000 0.170000 0.410000 ( 1.467640)
6
+
7
+
8
+ TokyoTyrant::RDB (Ruby)
9
+ user system total real
10
+ inserting data 0.300000 0.170000 0.470000 ( 1.481900)
11
+ reading data 0.410000 0.210000 0.620000 ( 1.705723)
12
+
13
+
14
+ TokyoTyrant (C)
15
+ user system total real
16
+ inserting data 0.130000 0.170000 0.300000 ( 1.251842)
17
+ reading data 0.120000 0.160000 0.280000 ( 1.539256)
18
+
19
+
20
+ Memcached (C) to Tyrant
21
+ user system total real
22
+ inserting data 0.200000 0.150000 0.350000 ( 1.814691)
23
+ reading data 0.180000 0.160000 0.340000 ( 1.358712)
24
+
25
+
26
+ Memcached (C) to Memcached
27
+ user system total real
28
+ inserting data 0.190000 0.140000 0.330000 ( 1.022183)
29
+ reading data 0.160000 0.140000 0.300000 ( 0.908084)
30
+
31
+
32
+ MemCache (Ruby)
33
+ user system total real
34
+ inserting data 1.200000 0.210000 1.410000 ( 2.329328)
35
+ reading data 1.510000 0.220000 1.730000 ( 2.721509)
36
+
37
+
38
+ Voldemort (Ruby)
39
+ user system total real
40
+ inserting data 18.290000 1.050000 19.340000 ( 37.562370)
41
+ reading data 9.040000 0.530000 9.570000 ( 15.145843)
42
+ =end
43
+
1
44
  require 'benchmark'
2
45
  require 'rubygems'
3
46
  require 'faker'
4
47
 
5
48
  data = []
6
49
 
7
- 100_000.times do |i|
50
+ 10_000.times do |i|
8
51
  data << Faker::Name.name
9
52
  end
10
53
 
11
- =begin
12
54
  require 'rufus/tokyo/tyrant'
13
55
 
14
56
  r = Rufus::Tokyo::Tyrant.new('127.0.0.1', 45000)
@@ -45,10 +87,9 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
45
87
  data.each_with_index { |e, i| nothing = rdb.get(i.to_s) }
46
88
  end
47
89
  end
48
- =end
49
90
 
50
91
  require 'tokyo_tyrant'
51
- t = TokyoTyrant::DB.new('127.0.0.1', 1978)
92
+ t = TokyoTyrant::DB.new('127.0.0.1', 45000)
52
93
  t.clear
53
94
 
54
95
  2.times { puts }
@@ -64,23 +105,6 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
64
105
  end
65
106
  end
66
107
 
67
- m = TokyoTyrant::MDB.new
68
- m.clear
69
-
70
- 2.times { puts }
71
- puts 'MDB'
72
-
73
- Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
74
- b.report('inserting data') do
75
- data.each_with_index { |e, i| m[i] = e }
76
- end
77
-
78
- b.report('reading data') do
79
- data.each_with_index { |e, i| nothing = m[i] }
80
- end
81
- end
82
-
83
- =begin
84
108
  require 'memcached'
85
109
  m = Memcached.new('127.0.0.1:45000')
86
110
  m.flush
@@ -131,4 +155,19 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
131
155
  data.each_with_index { |e, i| nothing = mc.get(i.to_s) }
132
156
  end
133
157
  end
134
- =end
158
+
159
+ require 'voldemort-rb'
160
+ vdb = VoldemortClient.new("test", "localhost:6666")
161
+ 2.times { puts }
162
+ puts 'Voldemort (Ruby)'
163
+
164
+ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
165
+ b.report('inserting data') do
166
+ data.each_with_index { |e, i| vdb.put(i.to_s, e) }
167
+ end
168
+
169
+ b.report('reading data') do
170
+ data.each_with_index { |e, i| nothing = vdb.get(i.to_s) }
171
+ end
172
+ end
173
+
@@ -1,3 +1,40 @@
1
+ =begin
2
+ Tokyo::TyrantTable (Ruby FFI)
3
+ user system total real
4
+ inserting data 0.840000 0.190000 1.030000 ( 3.214565)
5
+ reading data 1.310000 0.210000 1.520000 ( 3.024142)
6
+
7
+
8
+ TokyoTyrant::RDB (Ruby)
9
+ user system total real
10
+ inserting data 1.170000 0.240000 1.410000 ( 2.859321)
11
+ reading data 2.250000 0.660000 2.910000 ( 4.752291)
12
+
13
+
14
+ TokyoTyrant (C)
15
+ user system total real
16
+ inserting data 0.260000 0.180000 0.440000 ( 1.637843)
17
+ reading data 0.300000 0.170000 0.470000 ( 1.631104)
18
+
19
+
20
+ Memcached (C)
21
+ user system total real
22
+ inserting data 0.300000 0.160000 0.460000 ( 1.230830)
23
+ reading data 0.310000 0.140000 0.450000 ( 1.171531)
24
+
25
+
26
+ MemCache (Ruby)
27
+ user system total real
28
+ inserting data 2.080000 0.220000 2.300000 ( 3.379047)
29
+ reading data 2.220000 0.200000 2.420000 ( 4.018160)
30
+
31
+
32
+ Mongo
33
+ user system total real
34
+ inserting data 1.590000 0.130000 1.720000 ( 2.310027)
35
+ reading data 4.220000 0.380000 4.600000 ( 7.178335)
36
+ =end
37
+
1
38
  require 'benchmark'
2
39
  require 'rubygems'
3
40
  require 'faker'
@@ -7,14 +44,14 @@ require 'date'
7
44
  # the data
8
45
  #
9
46
 
10
- colnames = %w{ name sex birthday divisions }
47
+ colnames = %w{ _id name sex birthday divisions }
11
48
 
12
49
  $year = (1909 .. 2009).to_a
13
50
  $month = (1..12).to_a
14
51
  $day = (1..28).to_a # not bothering with month diffs
15
52
 
16
53
  def rbdate
17
- DateTime.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
54
+ Date.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
18
55
  end
19
56
 
20
57
  def rdiv
@@ -31,16 +68,16 @@ end
31
68
  def rgen
32
69
  (rand(2) == 1 ? 'male' : 'female')
33
70
  end
34
-
71
+
35
72
  data = [
36
- [ 'Alphonse Armalite', 'male', DateTime.new(1972, 10, 14), 'brd,dev' ],
37
- [ 'Brutus Beromunster', 'male', DateTime.new(1964, 07, 14), 'dev' ],
38
- [ 'Crystel Chucknorris', 'female', DateTime.new(1980, 07, 12), 'brd' ],
39
- [ 'Desree Dylan', 'female', DateTime.new(1954, 07, 13), 'brd,dev' ]
73
+ ['alphonse-armalite', 'Alphonse Armalite', 'male', Date.new(1972, 10, 14).to_s, 'brd,dev'],
74
+ ['brutus-beromunster', 'Brutus Beromunster', 'male', Date.new(1964, 07, 14).to_s, 'dev'],
75
+ ['crystel-chucknorris', 'Crystel Chucknorris', 'female', Date.new(1980, 07, 12).to_s, 'brd'],
76
+ ['desree-dylan', 'Desree Dylan', 'female', Date.new(1954, 07, 13).to_s, 'brd,dev']
40
77
  ]
41
78
 
42
79
  10_000.times do |i|
43
- data << [ Faker::Name.name, rgen, rbdate, rdiv]
80
+ data << [i.to_s, Faker::Name.name, rgen, rbdate.to_s, rdiv]
44
81
  end
45
82
 
46
83
  $find_name_list = []
@@ -112,14 +149,6 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
112
149
  b.report('reading data') do
113
150
  data1.each_with_index { |e, i| nothing = t[i] }
114
151
  end
115
-
116
- b.report('bulk writing data') do
117
- nothing = t.mput(data_h)
118
- end
119
-
120
- b.report('bulk reading data') do
121
- nothing = t.mget(0..9999)
122
- end
123
152
  end
124
153
 
125
154
  require 'memcached'
@@ -137,10 +166,6 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
137
166
  b.report('reading data') do
138
167
  data1.each_with_index { |e, i| nothing = m.get(i.to_s) }
139
168
  end
140
-
141
- b.report('bulk reading data') do
142
- nothing = m.get((0..9999).to_a.collect{|i| i.to_s})
143
- end
144
169
  end
145
170
 
146
171
  require 'memcache'
@@ -159,3 +184,20 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
159
184
  data1.each_with_index { |e, i| nothing = mc.get(i.to_s) }
160
185
  end
161
186
  end
187
+
188
+ require 'mongo'
189
+ db = Mongo::Connection.new.db("benchmark")
190
+ 2.times { puts }
191
+ puts 'Mongo'
192
+ mdb = db["data"]
193
+ mdb.remove
194
+
195
+ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
196
+ b.report('inserting data') do
197
+ data1.each_with_index { |e, i| mdb.insert(e) }
198
+ end
199
+
200
+ b.report('reading data') do
201
+ data1.each_with_index { |e, i| nothing = mdb.find_one({ "_id" => i.to_s }) }
202
+ end
203
+ end
@@ -123,22 +123,94 @@ extern TCLIST *vhashtolist(VALUE vhash){
123
123
  return list;
124
124
  }
125
125
 
126
+ extern TCLIST *vhashtoputlist(VALUE vhash){
127
+ VALUE vkey, vval, vkeys, vvals;
128
+ TCLIST *list;
129
+ int i, j;
130
+ vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
131
+ list = tclistnew();
132
+ for(i = 0; i < RARRAY_LEN(vkeys); i++){
133
+ vkey = rb_ary_entry(vkeys, i);
134
+ vkey = StringValueEx(vkey);
135
+
136
+ vvals = rb_hash_aref(vhash, vkey);
137
+ if (TYPE(vvals) == T_ARRAY){
138
+ for(j = 0; j < RARRAY_LEN(vvals); j++){
139
+ vval = rb_ary_entry(vvals, j);
140
+ vval = StringValueEx(vval);
141
+ tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
142
+ tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
143
+ }
144
+ } else {
145
+ vval = StringValueEx(vvals);
146
+ tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
147
+ tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
148
+ }
149
+ }
150
+ return list;
151
+ }
152
+
153
+ extern VALUE listtovhash(TCLIST *list){
154
+ VALUE vhash, vkey, vval, vvals;
155
+ const char *key, *val;
156
+ int i, num, ksiz, vsiz;
157
+ vhash = rb_hash_new();
158
+
159
+ num = tclistnum(list);
160
+ for(i = 0; i < num; i += 2){
161
+ key = tclistval(list, i, &ksiz);
162
+ val = tclistval(list, i + 1, &vsiz);
163
+ vkey = rb_str_new(key, ksiz);
164
+ vval = rb_str_new(val, vsiz);
165
+
166
+ vvals = rb_hash_aref(vhash, vkey);
167
+ if (TYPE(vvals) != T_ARRAY) vvals = rb_ary_new();
168
+ vvals = rb_ary_push(vvals, vval);
169
+ rb_hash_aset(vhash, vkey, vvals);
170
+ }
171
+ return vhash;
172
+ }
173
+
126
174
  VALUE mTokyoTyrant;
175
+
127
176
  VALUE eTokyoTyrantError;
177
+ VALUE eTokyoTyrantErrorInvalid;
178
+ VALUE eTokyoTyrantErrorNoHost;
179
+ VALUE eTokyoTyrantErrorRefused;
180
+ VALUE eTokyoTyrantErrorSend;
181
+ VALUE eTokyoTyrantErrorReceive;
182
+ VALUE eTokyoTyrantErrorKeep;
183
+ VALUE eTokyoTyrantErrorNoRecord;
184
+ VALUE eTokyoTyrantErrorMisc;
185
+
128
186
  VALUE cDB;
187
+ VALUE cBDB;
129
188
  VALUE cTable;
130
189
  VALUE cQuery;
131
- VALUE cMDB;
190
+ VALUE cConstistentHash;
132
191
 
133
192
  void Init_tokyo_tyrant(){
134
193
  mTokyoTyrant = rb_define_module("TokyoTyrant");
194
+
135
195
  eTokyoTyrantError = rb_define_class("TokyoTyrantError", rb_eStandardError);
196
+ eTokyoTyrantErrorInvalid = rb_define_class("TokyoTyrantErrorInvalid", eTokyoTyrantError);
197
+ eTokyoTyrantErrorNoHost = rb_define_class("TokyoTyrantErrorNoHost", eTokyoTyrantError);
198
+ eTokyoTyrantErrorRefused = rb_define_class("TokyoTyrantErrorRefused", eTokyoTyrantError);
199
+ eTokyoTyrantErrorSend = rb_define_class("TokyoTyrantErrorSend", eTokyoTyrantError);
200
+ eTokyoTyrantErrorReceive = rb_define_class("TokyoTyrantErrorReceive", eTokyoTyrantError);
201
+ eTokyoTyrantErrorKeep = rb_define_class("TokyoTyrantErrorKeep", eTokyoTyrantError);
202
+ eTokyoTyrantErrorNoRecord = rb_define_class("TokyoTyrantErrorNoRecord", eTokyoTyrantError);
203
+ eTokyoTyrantErrorMisc = rb_define_class("TokyoTyrantErrorMisc", eTokyoTyrantError);
204
+
136
205
  init_mod();
137
206
 
138
207
  cDB = rb_define_class_under(mTokyoTyrant, "DB", rb_cObject);
139
208
  rb_include_module(cDB, mTokyoTyrant);
140
209
  init_db();
141
210
 
211
+ cBDB = rb_define_class_under(mTokyoTyrant, "BDB", cDB);
212
+ init_bdb();
213
+
142
214
  cTable = rb_define_class_under(mTokyoTyrant, "Table", rb_cObject);
143
215
  rb_include_module(cTable, mTokyoTyrant);
144
216
  init_table();
@@ -146,6 +218,6 @@ void Init_tokyo_tyrant(){
146
218
  cQuery = rb_define_class_under(mTokyoTyrant, "Query", rb_cObject);
147
219
  init_query();
148
220
 
149
- cMDB = rb_define_class_under(mTokyoTyrant, "MDB", rb_cObject);
150
- init_utils();
221
+ cConstistentHash = rb_define_class_under(mTokyoTyrant, "ConstistentHash", rb_cObject);
222
+ init_consistent_hash();
151
223
  }