rambling-trie 0.9.2 → 0.9.3
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.
- checksums.yaml +4 -4
- data/Gemfile +12 -3
- data/README.md +1 -0
- data/lib/rambling/trie.rb +3 -2
- data/lib/rambling/trie/container.rb +7 -3
- data/lib/rambling/trie/enumerable.rb +3 -0
- data/lib/rambling/trie/forwardable.rb +16 -0
- data/lib/rambling/trie/invalid_operation.rb +2 -0
- data/lib/rambling/trie/node.rb +4 -5
- data/lib/rambling/trie/raw_node.rb +7 -9
- data/lib/rambling/trie/tasks/helpers/performance_report.rb +17 -0
- data/lib/rambling/trie/tasks/performance.rb +4 -0
- data/lib/rambling/trie/tasks/performance/benchmark.rb +22 -45
- data/lib/rambling/trie/tasks/performance/flamegraph.rb +119 -0
- data/lib/rambling/trie/tasks/performance/profile/call_tree.rb +65 -56
- data/lib/rambling/trie/tasks/performance/profile/memory.rb +69 -43
- data/lib/rambling/trie/version.rb +1 -1
- data/rambling-trie.gemspec +1 -5
- data/spec/assets/{test_words.txt → test_words.en_US.txt} +0 -0
- data/spec/assets/test_words.es_DO.txt +23 -0
- data/spec/integration/rambling/trie_spec.rb +17 -9
- data/spec/lib/rambling/trie/container_spec.rb +6 -0
- data/spec/lib/rambling/trie/node_spec.rb +0 -5
- data/spec/lib/rambling/trie/plain_text_reader_spec.rb +1 -1
- data/spec/lib/rambling/trie_spec.rb +2 -2
- data/spec/spec_helper.rb +7 -0
- metadata +9 -86
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -31
- data/.rspec +0 -1
- data/.travis.yml +0 -26
- data/assets/dictionaries/words_with_friends.txt +0 -172820
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54be3d6a000a38c0864250d0951a1986b2ceac2c
|
4
|
+
data.tar.gz: 5a8b13f581ce79c239f71e7e96c014572697f0c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62bf472c3abfc664ca22e2df3ba55254d3e03e1d66ab7f3f64bba4755feaf6e4ce92de604ff5c7b479056840734b4e3ca0be4707af447f0521c327d1bbc274e6
|
7
|
+
data.tar.gz: c13d4ce29e89093292268426240cc543026f11a4e0747a33c65bcd7950b156629a39ac61a9a5a78a95320de82d734680a532a043ac78a4c56e0334e746f9bb72
|
data/Gemfile
CHANGED
@@ -1,13 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
source 'https://rubygems.org'
|
2
3
|
|
3
4
|
gemspec
|
4
5
|
|
5
|
-
gem 'coveralls', require: false
|
6
|
-
|
7
6
|
group :development do
|
8
|
-
gem '
|
7
|
+
gem 'ruby-prof'
|
8
|
+
gem 'memory_profiler'
|
9
|
+
gem 'benchmark-ips'
|
10
|
+
gem 'flamegraph'
|
11
|
+
gem 'stackprof'
|
9
12
|
end
|
10
13
|
|
11
14
|
group :test do
|
15
|
+
gem 'simplecov', require: false
|
16
|
+
gem 'codeclimate-test-reporter', require: false
|
17
|
+
gem 'coveralls', require: false
|
18
|
+
end
|
19
|
+
|
20
|
+
group :local do
|
12
21
|
gem 'guard-rspec'
|
13
22
|
end
|
data/README.md
CHANGED
data/lib/rambling/trie.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
%w{
|
3
|
-
compression compressor inspector container enumerable
|
4
|
-
plain_text_reader node missing_node compressed_node
|
3
|
+
forwardable compression compressor inspector container enumerable
|
4
|
+
invalid_operation plain_text_reader node missing_node compressed_node
|
5
|
+
raw_node version
|
5
6
|
}.each do |file|
|
6
7
|
require File.join('rambling', 'trie', file)
|
7
8
|
end
|
@@ -2,8 +2,7 @@ module Rambling
|
|
2
2
|
module Trie
|
3
3
|
# Wrapper on top of Trie data structure.
|
4
4
|
class Container
|
5
|
-
extend ::Forwardable
|
6
|
-
|
5
|
+
extend Rambling::Trie::Forwardable
|
7
6
|
include ::Enumerable
|
8
7
|
|
9
8
|
delegate [
|
@@ -13,6 +12,7 @@ module Rambling
|
|
13
12
|
:children_tree,
|
14
13
|
:compressed?,
|
15
14
|
:each,
|
15
|
+
:to_a,
|
16
16
|
:has_key?,
|
17
17
|
:inspect,
|
18
18
|
:letter,
|
@@ -21,6 +21,10 @@ module Rambling
|
|
21
21
|
:to_s
|
22
22
|
] => :root
|
23
23
|
|
24
|
+
# The root node of this trie.
|
25
|
+
# @return [Node] the root node of this trie.
|
26
|
+
attr_reader :root
|
27
|
+
|
24
28
|
# Creates a new Trie.
|
25
29
|
# @param [Node] root the root node for the trie
|
26
30
|
# @param [Compressor] compressor responsible for compressing the trie
|
@@ -81,7 +85,7 @@ module Rambling
|
|
81
85
|
private
|
82
86
|
|
83
87
|
attr_reader :compressor
|
84
|
-
|
88
|
+
attr_writer :root
|
85
89
|
|
86
90
|
def default_root
|
87
91
|
Rambling::Trie::RawNode.new
|
@@ -4,6 +4,9 @@ module Rambling
|
|
4
4
|
module Enumerable
|
5
5
|
include ::Enumerable
|
6
6
|
|
7
|
+
# Returns number of words contained in the trie. See
|
8
|
+
# {https://ruby-doc.org/core-2.4.0/Enumerable.html#method-i-count
|
9
|
+
# Enumerable}
|
7
10
|
alias_method :size, :count
|
8
11
|
|
9
12
|
# Iterates over the words contained in the trie.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rambling
|
2
|
+
module Trie
|
3
|
+
# Provides delegation behavior
|
4
|
+
module Forwardable
|
5
|
+
def delegate delegated_methods_to_delegated_to
|
6
|
+
delegated_methods_to_delegated_to.each do |methods, delegated_to|
|
7
|
+
methods.each do |method|
|
8
|
+
define_method method do |*args|
|
9
|
+
send(delegated_to).send method, *args
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,6 +2,8 @@ module Rambling
|
|
2
2
|
module Trie
|
3
3
|
# Raised when trying to execute an invalid operation on a Trie data structure.
|
4
4
|
class InvalidOperation < Exception
|
5
|
+
# Creates a new InvalidOperation exception.
|
6
|
+
# @param [String, nil] message the exception message.
|
5
7
|
def initialize message = nil
|
6
8
|
super
|
7
9
|
end
|
data/lib/rambling/trie/node.rb
CHANGED
@@ -2,7 +2,10 @@ module Rambling
|
|
2
2
|
module Trie
|
3
3
|
# A representation of a node in the Trie data structure.
|
4
4
|
class Node
|
5
|
-
extend ::Forwardable
|
5
|
+
extend Rambling::Trie::Forwardable
|
6
|
+
include Rambling::Trie::Compression
|
7
|
+
include Rambling::Trie::Enumerable
|
8
|
+
include Rambling::Trie::Inspector
|
6
9
|
|
7
10
|
delegate [
|
8
11
|
:[],
|
@@ -11,10 +14,6 @@ module Rambling
|
|
11
14
|
:has_key?
|
12
15
|
] => :children_tree
|
13
16
|
|
14
|
-
include Rambling::Trie::Compression
|
15
|
-
include Rambling::Trie::Enumerable
|
16
|
-
include Rambling::Trie::Inspector
|
17
|
-
|
18
17
|
# Letter or letters corresponding to this node.
|
19
18
|
# @return [Symbol, nil] the corresponding letter(s) or nil.
|
20
19
|
attr_reader :letter
|
@@ -54,15 +54,6 @@ module Rambling
|
|
54
54
|
false
|
55
55
|
end
|
56
56
|
|
57
|
-
protected
|
58
|
-
|
59
|
-
def closest_node chars
|
60
|
-
letter = chars.slice!(0).to_sym
|
61
|
-
child = children_tree[letter]
|
62
|
-
|
63
|
-
child ? child.scan(chars) : Rambling::Trie::MissingNode.new
|
64
|
-
end
|
65
|
-
|
66
57
|
private
|
67
58
|
|
68
59
|
def add_to_children_tree word
|
@@ -77,6 +68,13 @@ module Rambling
|
|
77
68
|
node.letter = letter
|
78
69
|
children_tree[letter] = node
|
79
70
|
end
|
71
|
+
|
72
|
+
def closest_node chars
|
73
|
+
letter = chars.slice!(0).to_sym
|
74
|
+
child = children_tree[letter]
|
75
|
+
|
76
|
+
child ? child.scan(chars) : Rambling::Trie::MissingNode.new
|
77
|
+
end
|
80
78
|
end
|
81
79
|
end
|
82
80
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class PerformanceReport
|
2
|
+
attr_reader :output
|
3
|
+
|
4
|
+
def initialize output = $stdout.dup
|
5
|
+
@output = output
|
6
|
+
end
|
7
|
+
|
8
|
+
def start name
|
9
|
+
output.puts
|
10
|
+
output.puts "#{name} for rambling-trie version #{Rambling::Trie::VERSION}"
|
11
|
+
output.puts
|
12
|
+
end
|
13
|
+
|
14
|
+
def finish
|
15
|
+
output.close
|
16
|
+
end
|
17
|
+
end
|
@@ -3,9 +3,13 @@ require 'benchmark'
|
|
3
3
|
require 'ruby-prof'
|
4
4
|
require 'memory_profiler'
|
5
5
|
require 'benchmark/ips'
|
6
|
+
require 'flamegraph'
|
6
7
|
require_relative 'helpers/path'
|
8
|
+
require_relative 'helpers/time'
|
9
|
+
require_relative 'helpers/performance_report'
|
7
10
|
require_relative 'performance/directory'
|
8
11
|
require_relative 'performance/benchmark'
|
12
|
+
require_relative 'performance/flamegraph'
|
9
13
|
require_relative 'performance/profile/call_tree'
|
10
14
|
require_relative 'performance/profile/memory'
|
11
15
|
require_relative 'performance/all'
|
@@ -1,20 +1,6 @@
|
|
1
|
-
require_relative '../helpers/path'
|
2
|
-
|
3
1
|
namespace :performance do
|
4
2
|
include Helpers::Path
|
5
3
|
|
6
|
-
class BenchmarkReport
|
7
|
-
attr_reader :output
|
8
|
-
|
9
|
-
def initialize output
|
10
|
-
@output = output
|
11
|
-
end
|
12
|
-
|
13
|
-
def finish
|
14
|
-
output.close
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
4
|
class BenchmarkMeasurement
|
19
5
|
def initialize output
|
20
6
|
@output = output
|
@@ -42,10 +28,6 @@ namespace :performance do
|
|
42
28
|
end
|
43
29
|
end
|
44
30
|
|
45
|
-
def banner
|
46
|
-
output.puts "\nBenchmark for rambling-trie version #{Rambling::Trie::VERSION}"
|
47
|
-
end
|
48
|
-
|
49
31
|
private
|
50
32
|
|
51
33
|
attr_reader :output
|
@@ -64,23 +46,20 @@ namespace :performance do
|
|
64
46
|
end
|
65
47
|
end
|
66
48
|
|
67
|
-
def
|
68
|
-
@
|
49
|
+
def performance_report= performance_report
|
50
|
+
@performance_report = performance_report
|
69
51
|
end
|
70
52
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
@benchmark_report
|
53
|
+
def performance_report
|
54
|
+
@performance_report ||= PerformanceReport.new
|
75
55
|
end
|
76
56
|
|
77
57
|
def output
|
78
|
-
|
58
|
+
performance_report.output
|
79
59
|
end
|
80
60
|
|
81
61
|
def generate_lookups_benchmark filename = nil
|
82
62
|
measure = BenchmarkMeasurement.new output
|
83
|
-
measure.banner
|
84
63
|
|
85
64
|
trie = Rambling::Trie.create dictionary
|
86
65
|
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
@@ -102,7 +81,6 @@ namespace :performance do
|
|
102
81
|
|
103
82
|
def generate_scans_benchmark filename = nil
|
104
83
|
measure = BenchmarkMeasurement.new output
|
105
|
-
measure.banner
|
106
84
|
|
107
85
|
words = {
|
108
86
|
hi: 1_000,
|
@@ -128,38 +106,37 @@ namespace :performance do
|
|
128
106
|
|
129
107
|
namespace :benchmark do
|
130
108
|
namespace :output do
|
131
|
-
desc 'Set task reporting output to stdout'
|
132
|
-
task :stdout do
|
133
|
-
self.benchmark_report = BenchmarkReport.new IO.new(1)
|
134
|
-
end
|
135
|
-
|
136
109
|
desc 'Set task reporting output to file'
|
137
110
|
task file: ['performance:directory'] do
|
138
111
|
path = path 'reports', Rambling::Trie::VERSION, 'benchmark'
|
139
112
|
file = File.open path, 'a+'
|
140
|
-
self.
|
113
|
+
self.performance_report = PerformanceReport.new file
|
141
114
|
end
|
142
115
|
|
143
116
|
desc 'Close output stream'
|
144
117
|
task :close do
|
145
|
-
|
118
|
+
performance_report.finish
|
146
119
|
end
|
147
120
|
end
|
148
121
|
|
122
|
+
desc 'Output banner'
|
123
|
+
task :banner do
|
124
|
+
performance_report.start 'Benchmark'
|
125
|
+
end
|
126
|
+
|
149
127
|
desc 'Generate lookups performance benchmark report'
|
150
|
-
task :
|
128
|
+
task lookups: :banner do
|
151
129
|
generate_lookups_benchmark
|
152
130
|
end
|
153
131
|
|
154
132
|
desc 'Generate scans performance benchmark report'
|
155
|
-
task :
|
133
|
+
task scans: :banner do
|
156
134
|
generate_scans_benchmark
|
157
135
|
end
|
158
136
|
|
159
137
|
desc 'Generate creation performance benchmark report'
|
160
|
-
task :
|
138
|
+
task creation: :banner do
|
161
139
|
measure = BenchmarkMeasurement.new output
|
162
|
-
measure.banner
|
163
140
|
|
164
141
|
output.puts '==> Creation'
|
165
142
|
output.puts '`Rambling::Trie.create`'
|
@@ -170,9 +147,8 @@ namespace :performance do
|
|
170
147
|
end
|
171
148
|
|
172
149
|
desc 'Generate compression performance benchmark report'
|
173
|
-
task :
|
150
|
+
task compression: :banner do
|
174
151
|
measure = BenchmarkMeasurement.new output
|
175
|
-
measure.banner
|
176
152
|
|
177
153
|
output.puts '==> Compression'
|
178
154
|
output.puts '`compress!`'
|
@@ -188,22 +164,23 @@ namespace :performance do
|
|
188
164
|
|
189
165
|
desc 'Generate all performance benchmark reports'
|
190
166
|
task all: [
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
167
|
+
:creation,
|
168
|
+
:compression,
|
169
|
+
:lookups,
|
170
|
+
:scans,
|
195
171
|
]
|
196
172
|
|
197
173
|
namespace :all do
|
198
174
|
desc "Generate and store performance benchmark report in reports/#{Rambling::Trie::VERSION}"
|
199
175
|
task save: [
|
200
176
|
'output:file',
|
201
|
-
|
177
|
+
:all
|
202
178
|
]
|
203
179
|
end
|
204
180
|
|
205
181
|
desc 'Compare ips for different implementations (changes over time)'
|
206
182
|
task :compare do
|
183
|
+
require 'benchmark/ips'
|
207
184
|
Benchmark.ips do |b|
|
208
185
|
hash = { 'thing' => 'gniht' }
|
209
186
|
|
@@ -0,0 +1,119 @@
|
|
1
|
+
namespace :performance do
|
2
|
+
include Helpers::Path
|
3
|
+
include Helpers::Time
|
4
|
+
|
5
|
+
def performance_report
|
6
|
+
@performance_report ||= PerformanceReport.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def output
|
10
|
+
performance_report.output
|
11
|
+
end
|
12
|
+
|
13
|
+
class FlamegraphProfile
|
14
|
+
def initialize filename
|
15
|
+
@filename = filename
|
16
|
+
end
|
17
|
+
|
18
|
+
def perform times, params = nil
|
19
|
+
params = Array params
|
20
|
+
params << nil unless params.any?
|
21
|
+
|
22
|
+
dirname = path 'reports', Rambling::Trie::VERSION, 'flamegraph', time
|
23
|
+
FileUtils.mkdir_p dirname
|
24
|
+
path = File.join dirname, "#{filename}.html"
|
25
|
+
|
26
|
+
result = Flamegraph.generate path do
|
27
|
+
params.each do |param|
|
28
|
+
times.times do
|
29
|
+
yield param
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :filename
|
38
|
+
end
|
39
|
+
|
40
|
+
namespace :flamegraph do
|
41
|
+
desc 'Output banner'
|
42
|
+
task :banner do
|
43
|
+
performance_report.start 'Flamegraph'
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'Generate flamegraph reports for creation'
|
47
|
+
task creation: ['performance:directory', :banner] do
|
48
|
+
output.puts 'Generating flamegraph reports for creation...'
|
49
|
+
|
50
|
+
flamegraph = FlamegraphProfile.new 'new-trie'
|
51
|
+
flamegraph.perform 1 do
|
52
|
+
trie = Rambling::Trie.create dictionary
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Generate flamegraph reports for compression'
|
57
|
+
task compression: ['performance:directory', :banner] do
|
58
|
+
output.puts 'Generating flamegraph reports for compression...'
|
59
|
+
|
60
|
+
tries = [ Rambling::Trie.create(dictionary) ]
|
61
|
+
|
62
|
+
flamegraph = FlamegraphProfile.new 'compressed-trie'
|
63
|
+
flamegraph.perform 1, tries do |trie|
|
64
|
+
trie.compress!
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc 'Generate flamegraph reports for lookups'
|
70
|
+
task lookups: ['performance:directory', :banner] do
|
71
|
+
output.puts 'Generating flamegraph reports for lookups...'
|
72
|
+
|
73
|
+
words = %w(hi help beautiful impressionism anthropological)
|
74
|
+
|
75
|
+
trie = Rambling::Trie.create dictionary
|
76
|
+
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
77
|
+
|
78
|
+
[ trie, compressed_trie ].each do |trie|
|
79
|
+
prefix = "#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie"
|
80
|
+
|
81
|
+
flamegraph = FlamegraphProfile.new "#{prefix}-word"
|
82
|
+
flamegraph.perform 1, words do |word|
|
83
|
+
trie.word? word
|
84
|
+
end
|
85
|
+
|
86
|
+
flamegraph = FlamegraphProfile.new "#{prefix}-partial-word"
|
87
|
+
flamegraph.perform 1, words do |word|
|
88
|
+
trie.partial_word? word
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'Generate flamegraph reports for scans'
|
94
|
+
task scans: ['performance:directory', :banner] do
|
95
|
+
output.puts 'Generating flamegraph reports for scans...'
|
96
|
+
|
97
|
+
words = %w(hi help beautiful impressionism anthropological)
|
98
|
+
|
99
|
+
trie = Rambling::Trie.create dictionary
|
100
|
+
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
101
|
+
|
102
|
+
[ trie, compressed_trie ].each do |trie|
|
103
|
+
prefix = "#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie"
|
104
|
+
flamegraph = FlamegraphProfile.new "#{prefix}-scan"
|
105
|
+
flamegraph.perform 1, words do |word|
|
106
|
+
trie.scan(word).size
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
desc 'Generate all flamegraph reports'
|
112
|
+
task all: [
|
113
|
+
:creation,
|
114
|
+
:compression,
|
115
|
+
:lookups,
|
116
|
+
:scans,
|
117
|
+
]
|
118
|
+
end
|
119
|
+
end
|