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
@@ -1,31 +1,46 @@
|
|
1
|
-
require_relative '../../helpers/path'
|
2
|
-
require_relative '../../helpers/time'
|
3
|
-
|
4
1
|
namespace :performance do
|
5
2
|
namespace :profile do
|
6
3
|
include Helpers::Path
|
7
4
|
include Helpers::Time
|
8
5
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
6
|
+
def performance_report
|
7
|
+
@performance_report ||= PerformanceReport.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def output
|
11
|
+
performance_report.output
|
12
|
+
end
|
13
|
+
|
14
|
+
class CallTreeProfile
|
15
|
+
def initialize dirname
|
16
|
+
@dirname = dirname
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform times, params = nil
|
20
|
+
params = Array params
|
21
|
+
params << nil unless params.any?
|
12
22
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
23
|
+
result = RubyProf.profile merge_fibers: true do
|
24
|
+
params.each do |param|
|
25
|
+
times.times do
|
26
|
+
yield param
|
27
|
+
end
|
17
28
|
end
|
18
29
|
end
|
30
|
+
|
31
|
+
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, dirname
|
32
|
+
FileUtils.mkdir_p path
|
33
|
+
printer = RubyProf::CallTreePrinter.new result
|
34
|
+
printer.print path: path
|
19
35
|
end
|
20
36
|
|
21
|
-
|
22
|
-
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :dirname
|
23
40
|
end
|
24
41
|
|
25
42
|
def generate_lookups_call_tree
|
26
|
-
puts 'Generating call tree profiling reports for lookups...'
|
27
|
-
|
28
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
43
|
+
output.puts 'Generating call tree profiling reports for lookups...'
|
29
44
|
|
30
45
|
words = %w(hi help beautiful impressionism anthropological)
|
31
46
|
|
@@ -33,30 +48,24 @@ namespace :performance do
|
|
33
48
|
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
34
49
|
|
35
50
|
[ trie, compressed_trie ].each do |trie|
|
36
|
-
|
37
|
-
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, filename
|
38
|
-
FileUtils.mkdir_p path
|
51
|
+
prefix = "profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}"
|
39
52
|
|
40
|
-
|
53
|
+
call_tree_profile = CallTreeProfile.new "#{prefix}-word"
|
54
|
+
call_tree_profile.perform 200_000, words do
|
41
55
|
trie.word? word
|
42
56
|
end
|
43
57
|
|
44
|
-
|
45
|
-
|
46
|
-
FileUtils.mkdir_p path
|
47
|
-
|
48
|
-
profile 200_000, words, path do
|
58
|
+
call_tree_profile = CallTreeProfile.new "#{prefix}-partial-word"
|
59
|
+
call_tree_profile.perform 200_000, words do
|
49
60
|
trie.partial_word? word
|
50
61
|
end
|
51
62
|
end
|
52
63
|
|
53
|
-
puts 'Done'
|
64
|
+
output.puts 'Done'
|
54
65
|
end
|
55
66
|
|
56
67
|
def generate_scans_call_tree
|
57
|
-
puts 'Generating call tree profiling reports for scans...'
|
58
|
-
|
59
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
68
|
+
output.puts 'Generating call tree profiling reports for scans...'
|
60
69
|
|
61
70
|
words = {
|
62
71
|
hi: 1_000,
|
@@ -70,68 +79,68 @@ namespace :performance do
|
|
70
79
|
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
71
80
|
|
72
81
|
[ trie, compressed_trie ].each do |trie|
|
73
|
-
|
74
|
-
|
75
|
-
FileUtils.mkdir_p path
|
82
|
+
dirname = "profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}-scan"
|
83
|
+
call_tree_profile = CallTreeProfile.new dirname
|
76
84
|
|
77
85
|
words.each do |word, times|
|
78
|
-
|
86
|
+
call_tree_profile.perform times, word.to_s do |word|
|
79
87
|
trie.scan(word).size
|
80
88
|
end
|
81
89
|
end
|
82
90
|
end
|
83
91
|
|
84
|
-
puts 'Done'
|
92
|
+
output.puts 'Done'
|
85
93
|
end
|
86
94
|
|
87
95
|
namespace :call_tree do
|
96
|
+
desc 'Output banner'
|
97
|
+
task :banner do
|
98
|
+
performance_report.start 'Call Tree profile'
|
99
|
+
end
|
100
|
+
|
88
101
|
desc 'Generate call tree profiling reports for creation'
|
89
|
-
task creation: ['performance:directory'] do
|
90
|
-
puts 'Generating call tree profiling reports for creation...'
|
91
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
92
|
-
filename = "profile-new-trie"
|
93
|
-
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, filename
|
94
|
-
FileUtils.mkdir_p path
|
102
|
+
task creation: ['performance:directory', :banner] do
|
103
|
+
output.puts 'Generating call tree profiling reports for creation...'
|
95
104
|
|
96
|
-
|
105
|
+
call_tree_profile = CallTreeProfile.new 'profile-new-trie'
|
106
|
+
call_tree_profile.perform 5 do
|
97
107
|
trie = Rambling::Trie.create dictionary
|
98
108
|
end
|
109
|
+
|
110
|
+
output.puts 'Done'
|
99
111
|
end
|
100
112
|
|
101
113
|
desc 'Generate call tree profiling reports for compression'
|
102
|
-
task compression: ['performance:directory'] do
|
103
|
-
puts 'Generating call tree profiling reports for compression...'
|
104
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
105
|
-
|
106
|
-
filename = "profile-compressed-trie"
|
107
|
-
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, filename
|
108
|
-
FileUtils.mkdir_p path
|
114
|
+
task compression: ['performance:directory', :banner] do
|
115
|
+
output.puts 'Generating call tree profiling reports for compression...'
|
109
116
|
|
110
117
|
tries = []
|
111
118
|
5.times { tries << Rambling::Trie.create(dictionary) }
|
112
119
|
|
113
|
-
|
114
|
-
|
115
|
-
nil
|
120
|
+
call_tree_profile = CallTreeProfile.new 'profile-compressed-trie'
|
121
|
+
call_tree_profile.perform 5, tries do |trie|
|
122
|
+
trie.compress!; nil
|
116
123
|
end
|
124
|
+
|
125
|
+
output.puts 'Done'
|
117
126
|
end
|
118
127
|
|
119
128
|
desc 'Generate call tree profiling reports for lookups'
|
120
|
-
task lookups: ['performance:directory'] do
|
129
|
+
task lookups: ['performance:directory', :banner] do
|
121
130
|
generate_lookups_call_tree
|
122
131
|
end
|
123
132
|
|
124
133
|
desc 'Generate call tree profiling reports for scans'
|
125
|
-
task scans: ['performance:directory'] do
|
134
|
+
task scans: ['performance:directory', :banner] do
|
126
135
|
generate_scans_call_tree
|
127
136
|
end
|
128
137
|
|
129
138
|
desc 'Generate all call tree profiling reports'
|
130
139
|
task all: [
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
140
|
+
:creation,
|
141
|
+
:compression,
|
142
|
+
:lookups,
|
143
|
+
:scans,
|
135
144
|
]
|
136
145
|
end
|
137
146
|
end
|
@@ -1,55 +1,79 @@
|
|
1
|
-
require_relative '../../helpers/path'
|
2
|
-
require_relative '../../helpers/time'
|
3
|
-
|
4
1
|
namespace :performance do
|
5
2
|
namespace :profile do
|
6
3
|
include Helpers::Path
|
7
4
|
include Helpers::Time
|
8
5
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
def performance_report
|
7
|
+
@performance_report ||= PerformanceReport.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def output
|
11
|
+
performance_report.output
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
class MemoryProfile
|
15
|
+
def initialize name
|
16
|
+
@name = name
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
def perform
|
20
|
+
result = MemoryProfiler.report allow_files: 'lib/rambling/trie', ignore_files: 'lib/rambling/trie/tasks' do
|
21
|
+
with_gc_stats do
|
22
|
+
yield
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
dir = path 'reports', Rambling::Trie::VERSION, 'memory', time
|
27
|
+
FileUtils.mkdir_p dir
|
28
|
+
result.pretty_print to_file: File.join(dir, name)
|
21
29
|
end
|
22
30
|
|
23
|
-
|
24
|
-
|
25
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :name
|
34
|
+
end
|
35
|
+
|
36
|
+
def with_gc_stats
|
37
|
+
output.puts "Live objects before - #{GC.stat[:heap_live_slots]}"
|
38
|
+
yield
|
39
|
+
output.puts "Live objects after - #{GC.stat[:heap_live_slots]}"
|
26
40
|
end
|
27
41
|
|
28
42
|
namespace :memory do
|
43
|
+
desc 'Output banner'
|
44
|
+
task :banner do
|
45
|
+
performance_report.start 'Memory profile'
|
46
|
+
end
|
47
|
+
|
29
48
|
desc 'Generate memory profiling reports for creation'
|
30
|
-
task creation: ['performance:directory'] do
|
31
|
-
puts 'Generating memory profiling reports for creation...'
|
49
|
+
task creation: ['performance:directory', :banner] do
|
50
|
+
output.puts 'Generating memory profiling reports for creation...'
|
32
51
|
|
33
52
|
trie = nil
|
34
53
|
|
35
|
-
memory_profile
|
36
|
-
|
54
|
+
memory_profile = MemoryProfile.new 'memory-profile-new-trie'
|
55
|
+
memory_profile.perform do
|
56
|
+
trie = Rambling::Trie.create dictionary
|
37
57
|
end
|
38
58
|
end
|
39
59
|
|
40
60
|
desc 'Generate memory profiling reports for compression'
|
41
|
-
task compression: ['performance:directory'] do
|
61
|
+
task compression: ['performance:directory', :banner] do
|
62
|
+
output.puts 'Generating memory profiling reports for compression...'
|
42
63
|
trie = Rambling::Trie.create dictionary
|
43
64
|
|
44
|
-
memory_profile
|
45
|
-
|
65
|
+
memory_profile = MemoryProfile.new 'memory-profile-trie-and-compress'
|
66
|
+
memory_profile.perform do
|
67
|
+
trie.compress!
|
46
68
|
end
|
47
69
|
|
48
70
|
with_gc_stats { GC.start }
|
49
71
|
end
|
50
72
|
|
51
73
|
desc 'Generate memory profiling reports for lookups'
|
52
|
-
task lookups: ['performance:directory'] do
|
74
|
+
task lookups: ['performance:directory', :banner] do
|
75
|
+
output.puts 'Generating memory profiling reports for lookups...'
|
76
|
+
|
53
77
|
words = %w(hi help beautiful impressionism anthropological)
|
54
78
|
|
55
79
|
trie = Rambling::Trie.create dictionary
|
@@ -57,24 +81,23 @@ namespace :performance do
|
|
57
81
|
[ trie, compressed_trie ].each do |trie|
|
58
82
|
times = 10
|
59
83
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
84
|
+
prefix = "memory-profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie"
|
85
|
+
name = "#{prefix}-word"
|
86
|
+
memory_profile = MemoryProfile.new name
|
87
|
+
memory_profile.perform do
|
88
|
+
words.each do |word|
|
89
|
+
times.times do
|
90
|
+
trie.word? word
|
67
91
|
end
|
68
92
|
end
|
69
93
|
end
|
70
94
|
|
71
|
-
name = "
|
72
|
-
memory_profile name
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
95
|
+
name = "#{prefix}-partial-word"
|
96
|
+
memory_profile = MemoryProfile.new name
|
97
|
+
memory_profile.perform do
|
98
|
+
words.each do |word|
|
99
|
+
times.times do
|
100
|
+
trie.partial_word? word
|
78
101
|
end
|
79
102
|
end
|
80
103
|
end
|
@@ -82,7 +105,9 @@ namespace :performance do
|
|
82
105
|
end
|
83
106
|
|
84
107
|
desc 'Generate memory profiling reports for scans'
|
85
|
-
task scans: ['performance:directory'] do
|
108
|
+
task scans: ['performance:directory', :banner] do
|
109
|
+
output.puts 'Generating memory profiling reports for scans...'
|
110
|
+
|
86
111
|
words = {
|
87
112
|
hi: 1,
|
88
113
|
help: 100,
|
@@ -95,7 +120,8 @@ namespace :performance do
|
|
95
120
|
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
96
121
|
[ trie, compressed_trie ].each do |trie|
|
97
122
|
name = "memory-profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie-scan"
|
98
|
-
memory_profile name
|
123
|
+
memory_profile = MemoryProfile.new name
|
124
|
+
memory_profile.perform do
|
99
125
|
words.each do |word, times|
|
100
126
|
times.times do
|
101
127
|
trie.scan(word.to_s).size
|
@@ -107,10 +133,10 @@ namespace :performance do
|
|
107
133
|
|
108
134
|
desc 'Generate all memory profiling reports'
|
109
135
|
task all: [
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
136
|
+
:creation,
|
137
|
+
:compression,
|
138
|
+
:lookups,
|
139
|
+
:scans,
|
114
140
|
]
|
115
141
|
end
|
116
142
|
end
|
data/rambling-trie.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.date = Time.now.strftime '%Y-%m-%d'
|
12
12
|
|
13
13
|
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename f }
|
14
|
-
gem.files = `git ls-files`.split "\n"
|
14
|
+
gem.files = `git ls-files -- {lib,*file,*.gemspec,LICENSE*,README*}`.split "\n"
|
15
15
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split "\n"
|
16
16
|
gem.require_paths = ['lib']
|
17
17
|
|
@@ -22,9 +22,5 @@ Gem::Specification.new do |gem|
|
|
22
22
|
|
23
23
|
gem.add_development_dependency 'rspec', '~> 3.5'
|
24
24
|
gem.add_development_dependency 'rake', '~> 12.0'
|
25
|
-
gem.add_development_dependency 'ruby-prof', '~> 0.16.2'
|
26
|
-
gem.add_development_dependency 'memory_profiler', '~> 0.9.7'
|
27
|
-
gem.add_development_dependency 'benchmark-ips', '~> 2.7.2'
|
28
25
|
gem.add_development_dependency 'yard', '~> 0.9.5'
|
29
|
-
gem.add_development_dependency 'redcarpet', '~> 3.3.4'
|
30
26
|
end
|
File without changes
|
@@ -53,20 +53,28 @@ describe Rambling::Trie do
|
|
53
53
|
describe 'with words provided directly' do
|
54
54
|
it_behaves_like 'a compressable trie' do
|
55
55
|
let(:words) { %w[a couple of words for our full trie integration test] }
|
56
|
-
let(:trie) { Rambling::Trie.create }
|
57
|
-
|
58
|
-
before do
|
59
|
-
words.each do |word|
|
60
|
-
trie << word
|
61
|
-
trie.add word
|
62
|
-
end
|
63
|
-
end
|
56
|
+
let(:trie) { Rambling::Trie.create { |t| words.each { |w| t << w } } }
|
64
57
|
end
|
65
58
|
end
|
66
59
|
|
67
60
|
describe 'with words from a file' do
|
68
61
|
it_behaves_like 'a compressable trie' do
|
69
|
-
let(:filepath) { File.join ::SPEC_ROOT, 'assets', 'test_words.txt' }
|
62
|
+
let(:filepath) { File.join ::SPEC_ROOT, 'assets', 'test_words.en_US.txt' }
|
63
|
+
let(:words) { File.readlines(filepath).map &:chomp! }
|
64
|
+
let(:trie) { Rambling::Trie.create filepath }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'with words with unicode characters' do
|
69
|
+
it_behaves_like 'a compressable trie' do
|
70
|
+
let(:words) { %w[poquísimas palabras para nuestra prueba de integración completa] }
|
71
|
+
let(:trie) { Rambling::Trie.create { |t| words.each { |w| t << w } } }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'with words with unicode characters from a file' do
|
76
|
+
it_behaves_like 'a compressable trie' do
|
77
|
+
let(:filepath) { File.join ::SPEC_ROOT, 'assets', 'test_words.en_US.txt' }
|
70
78
|
let(:words) { File.readlines(filepath).map &:chomp! }
|
71
79
|
let(:trie) { Rambling::Trie.create filepath }
|
72
80
|
end
|