hashtree 0.0.8 → 0.0.9
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.
- data/examples/benchmarks.rb +87 -82
- data/lib/hashtree.rb +21 -50
- data/lib/hashtree/version.rb +1 -1
- metadata +2 -2
data/examples/benchmarks.rb
CHANGED
@@ -3,6 +3,11 @@ require 'benchmark'
|
|
3
3
|
require 'hashtree'
|
4
4
|
require 'securerandom'
|
5
5
|
require 'digest'
|
6
|
+
require 'thread'
|
7
|
+
require 'monitor'
|
8
|
+
|
9
|
+
@lock = Monitor.new
|
10
|
+
@cv = @lock.new_cond
|
6
11
|
|
7
12
|
def gen_doc(i)
|
8
13
|
name = "John Doe #{i}"
|
@@ -40,20 +45,20 @@ Benchmark.bm do |x|
|
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
|
-
puts "Creating a HashTree with 100.000 documents with 4 Threads"
|
44
|
-
x.report do
|
45
|
-
@htree = HashTree.new
|
46
|
-
t = []
|
47
|
-
4.times do
|
48
|
-
t << Thread.new do
|
49
|
-
25_000.times do |i|
|
50
|
-
key, doc = gen_doc(i)
|
51
|
-
@htree[key] = doc
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
t.each(&:join)
|
56
|
-
end
|
48
|
+
# puts "Creating a HashTree with 100.000 documents with 4 Threads"
|
49
|
+
# x.report do
|
50
|
+
# @htree = HashTree.new
|
51
|
+
# t = []
|
52
|
+
# 4.times do
|
53
|
+
# t << Thread.new do
|
54
|
+
# 25_000.times do |i|
|
55
|
+
# key, doc = gen_doc(i)
|
56
|
+
# @htree[key] = doc
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
# t.each(&:join)
|
61
|
+
# end
|
57
62
|
|
58
63
|
puts "Reading 1.000 random documents"
|
59
64
|
x.report do
|
@@ -79,19 +84,19 @@ Benchmark.bm do |x|
|
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
82
|
-
puts "Reading 100.000 random documents with 4 Threads"
|
83
|
-
x.report do
|
84
|
-
t = []
|
85
|
-
4.times do
|
86
|
-
t << Thread.new do
|
87
|
-
25_000.times do |i|
|
88
|
-
key = "jdoe#{rand(100_000)}"
|
89
|
-
@htree[key]
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
t.each(&:join)
|
94
|
-
end
|
87
|
+
# puts "Reading 100.000 random documents with 4 Threads"
|
88
|
+
# x.report do
|
89
|
+
# t = []
|
90
|
+
# 4.times do
|
91
|
+
# t << Thread.new do
|
92
|
+
# 25_000.times do |i|
|
93
|
+
# key = "jdoe#{rand(100_000)}"
|
94
|
+
# @htree[key]
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
# t.each(&:join)
|
99
|
+
# end
|
95
100
|
|
96
101
|
puts "Doing 1 non-indexed query"
|
97
102
|
x.report do
|
@@ -101,67 +106,67 @@ Benchmark.bm do |x|
|
|
101
106
|
end
|
102
107
|
end
|
103
108
|
|
104
|
-
puts "Doing
|
109
|
+
puts "Doing 10 non-indexed queries"
|
105
110
|
x.report do
|
106
|
-
|
111
|
+
10.times do |i|
|
107
112
|
query = proc{ |key,doc| doc[:email] == "john.doe.#{rand(100000)}@example.com" }
|
108
113
|
@htree.select{ |key, doc| query.call(key,doc) }
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
112
|
-
puts "Doing 20 non-indexed queries with 4 threads"
|
113
|
-
x.report do
|
114
|
-
t = []
|
115
|
-
4.times do
|
116
|
-
t << Thread.new do
|
117
|
-
5.times do |i|
|
118
|
-
query = proc{ |key,doc| doc[:email] == "john.doe.#{rand(100000)}@example.com" }
|
119
|
-
@htree.select{ |key, doc| query.call(key,doc) }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
t.each(&:join)
|
124
|
-
end
|
125
|
-
|
126
|
-
puts "Doing 40 non-indexed queries and 40 updates with 4 threads"
|
127
|
-
x.report do
|
128
|
-
t = []
|
129
|
-
2.times do
|
130
|
-
t << Thread.new do
|
131
|
-
20.times do |i|
|
132
|
-
query = proc{ |key,doc| doc[:email] == "john.doe.#{rand(100000)}@example.com" }
|
133
|
-
@htree.select{ |key, doc| query.call(key,doc) }
|
134
|
-
end
|
135
|
-
end
|
136
|
-
t << Thread.new do
|
137
|
-
20.times do |i|
|
138
|
-
key = "jdoe#{rand(100_000)}"
|
139
|
-
@htree[key] = {}
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
t.each(&:join)
|
144
|
-
end
|
145
|
-
|
146
|
-
puts "Doing 100.000 random reads and 40 updates with 4 threads"
|
147
|
-
x.report do
|
148
|
-
t = []
|
149
|
-
2.times do
|
150
|
-
t << Thread.new do
|
151
|
-
20.times do |i|
|
152
|
-
5_000.times{ key = "jdoe#{rand(100_000)}"; @htree[key] }
|
153
|
-
end
|
154
|
-
end
|
155
|
-
t << Thread.new do
|
156
|
-
20.times do |i|
|
157
|
-
key = "jdoe#{rand(100_000)}"
|
158
|
-
@htree[key] = {}
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
t.each(&:join)
|
163
|
-
end
|
164
|
-
|
117
|
+
# puts "Doing 20 non-indexed queries with 4 threads"
|
118
|
+
# x.report do
|
119
|
+
# t = []
|
120
|
+
# 4.times do
|
121
|
+
# t << Thread.new do
|
122
|
+
# 5.times do |i|
|
123
|
+
# query = proc{ |key,doc| doc[:email] == "john.doe.#{rand(100000)}@example.com" }
|
124
|
+
# @htree.select{ |key, doc| query.call(key,doc) }
|
125
|
+
# end
|
126
|
+
# end
|
127
|
+
# end
|
128
|
+
# t.each(&:join)
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
# puts "Doing 40 non-indexed queries and 40 updates with 4 threads"
|
132
|
+
# x.report do
|
133
|
+
# t = []
|
134
|
+
# 2.times do
|
135
|
+
# t << Thread.new do
|
136
|
+
# 20.times do |i|
|
137
|
+
# query = proc{ |key,doc| doc[:email] == "john.doe.#{rand(100000)}@example.com" }
|
138
|
+
# @htree.select{ |key, doc| query.call(key,doc) }
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
# t << Thread.new do
|
142
|
+
# 20.times do |i|
|
143
|
+
# key = "jdoe#{rand(100_000)}"
|
144
|
+
# @htree[key] = {}
|
145
|
+
# end
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
# t.each(&:join)
|
149
|
+
# end
|
150
|
+
#
|
151
|
+
# puts "Doing 100.000 random reads and 40 updates with 4 threads"
|
152
|
+
# x.report do
|
153
|
+
# t = []
|
154
|
+
# 2.times do
|
155
|
+
# t << Thread.new do
|
156
|
+
# 20.times do |i|
|
157
|
+
# 5_000.times{ key = "jdoe#{rand(100_000)}"; @htree[key] }
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
# t << Thread.new do
|
161
|
+
# 20.times do |i|
|
162
|
+
# key = "jdoe#{rand(100_000)}"
|
163
|
+
# @htree[key] = {}
|
164
|
+
# end
|
165
|
+
# end
|
166
|
+
# end
|
167
|
+
# t.each(&:join)
|
168
|
+
# end
|
169
|
+
#
|
165
170
|
# puts "Doing 100 non-indexed queries"
|
166
171
|
# x.report do
|
167
172
|
# 100.times do |i|
|
data/lib/hashtree.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'digest'
|
3
3
|
require 'securerandom'
|
4
|
-
require 'thread'
|
5
|
-
require 'monitor'
|
6
4
|
|
7
5
|
require "hashtree/version"
|
8
6
|
|
9
7
|
class HashTree
|
10
8
|
|
11
|
-
attr_reader :index, :branches, :settings
|
9
|
+
attr_reader :index, :branches, :settings, :reading, :writing
|
12
10
|
|
13
11
|
def initialize(settings = {})
|
14
12
|
@settings = {
|
@@ -17,10 +15,6 @@ class HashTree
|
|
17
15
|
@root = {}
|
18
16
|
@branches = {}
|
19
17
|
@free = {}
|
20
|
-
@lock = Mutex.new
|
21
|
-
@rootcv = ConditionVariable.new
|
22
|
-
@branchcv = ConditionVariable.new
|
23
|
-
@freecv = ConditionVariable.new
|
24
18
|
end
|
25
19
|
|
26
20
|
def [](key)
|
@@ -29,23 +23,25 @@ class HashTree
|
|
29
23
|
end
|
30
24
|
|
31
25
|
def []=(key, value)
|
32
|
-
@
|
33
|
-
|
34
|
-
id ? update(id, value) : create(key, value)
|
35
|
-
end
|
26
|
+
id = @root[key]
|
27
|
+
id ? update(id, value) : create(key, value)
|
36
28
|
end
|
37
29
|
|
38
30
|
def delete(key)
|
39
|
-
@
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
31
|
+
id = @root[key]
|
32
|
+
if id
|
33
|
+
doc = read(id)
|
34
|
+
destroy(id)
|
35
|
+
@root.delete(key)
|
36
|
+
return doc
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def select(&block)
|
43
|
+
@root.select do |key, id|
|
44
|
+
yield(key, read(id))
|
49
45
|
end
|
50
46
|
end
|
51
47
|
|
@@ -62,26 +58,6 @@ class HashTree
|
|
62
58
|
@root.has_key?(key)
|
63
59
|
end
|
64
60
|
|
65
|
-
def select(&block)
|
66
|
-
results = {}
|
67
|
-
keys = @root.keys
|
68
|
-
keys.each do |key|
|
69
|
-
leaf = self[key]
|
70
|
-
results[key] = leaf if yield(key, leaf)
|
71
|
-
end
|
72
|
-
return results
|
73
|
-
end
|
74
|
-
|
75
|
-
def each(&block)
|
76
|
-
results = {}
|
77
|
-
keys = @root.keys
|
78
|
-
keys.each do |key|
|
79
|
-
leaf = self[key]
|
80
|
-
yield(key, leaf)
|
81
|
-
end
|
82
|
-
return results
|
83
|
-
end
|
84
|
-
|
85
61
|
def branch(key)
|
86
62
|
id = @root[key]
|
87
63
|
if id
|
@@ -94,17 +70,12 @@ class HashTree
|
|
94
70
|
|
95
71
|
private
|
96
72
|
|
97
|
-
def translate_id(id)
|
98
|
-
branch_id, leaf_id = id[0..31], id[32..64]
|
99
|
-
return branch_id, leaf_id
|
100
|
-
end
|
101
|
-
|
102
73
|
def generate_id
|
103
74
|
Digest::SHA256.hexdigest(SecureRandom.uuid)
|
104
75
|
end
|
105
76
|
|
106
77
|
def read(id)
|
107
|
-
branch_id, leaf_id =
|
78
|
+
branch_id, leaf_id = id[0..31], id[32..64]
|
108
79
|
begin
|
109
80
|
@branches[branch_id][leaf_id]
|
110
81
|
rescue
|
@@ -122,7 +93,7 @@ class HashTree
|
|
122
93
|
@free.delete(branch_id) if branch.size >= @settings[:max_branch_size]
|
123
94
|
else
|
124
95
|
id = generate_id
|
125
|
-
branch_id, leaf_id =
|
96
|
+
branch_id, leaf_id = id[0..31], id[32..64]
|
126
97
|
@root[key] = id
|
127
98
|
@branches[branch_id] = {}
|
128
99
|
@branches[branch_id][leaf_id] = value
|
@@ -131,7 +102,7 @@ class HashTree
|
|
131
102
|
end
|
132
103
|
|
133
104
|
def update(id, value)
|
134
|
-
branch_id, leaf_id =
|
105
|
+
branch_id, leaf_id = id[0..31], id[32..64]
|
135
106
|
begin
|
136
107
|
@branches[branch_id][leaf_id] = value
|
137
108
|
rescue
|
@@ -140,7 +111,7 @@ class HashTree
|
|
140
111
|
end
|
141
112
|
|
142
113
|
def destroy(id)
|
143
|
-
branch_id, leaf_id =
|
114
|
+
branch_id, leaf_id = id[0..31], id[32..64]
|
144
115
|
value = @branches[branch_id].delete(leaf_id)
|
145
116
|
if @branches[branch_id].size == 0
|
146
117
|
@branches.delete(branch_id)
|
data/lib/hashtree/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashtree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|